home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-src / machines / ppc / machine.c next >
C/C++ Source or Header  |  1999-01-01  |  71KB  |  1,927 lines

  1. /*  Code generator for a PPC RISC cpu with 32 general purpose,  */
  2. /*  32 floating point and 8 condition code registers.           */
  3.  
  4. #include "supp.h"
  5.  
  6. static char FILE_[]=__FILE__;
  7.  
  8. /*  Public data that MUST be there.                             */
  9.  
  10. /* Name and copyright. */
  11. char cg_copyright[]="vbcc code-generator for PPC V0.3 (c) in 1997-99 by Volker Barthelmann";
  12.  
  13. /*  Commandline-flags the code-generator accepts                */
  14. int g_flags[MAXGF]={STRINGFLAG,STRINGFLAG,0,0,0,0,
  15.                     0,0,0,0,0,
  16.                     0,0,0};
  17. char *g_flags_name[MAXGF]={"cpu","fpu","const-in-data","sd","merge-constants","fsub-zero",
  18.                            "elf","amiga-align","no-regnames","peephole","setccs",
  19.                            "use-lmw","poweropen","sc"};
  20. union ppi g_flags_val[MAXGF];
  21.  
  22. /*  Alignment-requirements for all types in bytes.              */
  23. zlong align[16];
  24.  
  25. /*  Alignment that is sufficient for every object.              */
  26. zlong maxalign;
  27.  
  28. /*  CHAR_BIT for the target machine.                            */
  29. zlong char_bit;
  30.  
  31. /*  Tabelle fuer die Groesse der einzelnen Typen                */
  32. zlong sizetab[16];
  33.  
  34. /*  Minimum and Maximum values each type can have.              */
  35. /*  Must be initialized in init_cg().                           */
  36. zlong t_min[32];
  37. zulong t_max[32];
  38.  
  39. /*  Names of all registers.                                     */
  40. char *regnames[MAXR+1]={"noreg",
  41.                         "r0","r1","r2","r10","r9","r8","r7","r6",
  42.                         "r5","r4","r3","r11","r12","r13","r31","r30",
  43.                         "r29","r28","r27","r26","r25","r24","r23","r22",
  44.                         "r21","r20","r19","r18","r17","r16","r15","r14",
  45.                         "f9","f10","f0","f11","f12","f13","f8","f7",
  46.                         "f6","f5","f4","f3","f2","f1","f14","f15",
  47.                         "f16","f17","f18","f19","f20","f21","f22","f23",
  48.                         "f24","f25","f26","f27","f28","f29","f30","f31",
  49.                         "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7",
  50.                         "cnt"};
  51.  
  52. /*  The Size of each register in bytes.                         */
  53. zlong regsize[MAXR+1];
  54.  
  55. /*  Type which can store each register. */
  56. struct Typ *regtype[MAXR+1];
  57.  
  58. /*  regsa[reg]!=0 if a certain register is allocated and should */
  59. /*  not be used by the compiler pass.                           */
  60. int regsa[MAXR+1];
  61.  
  62. /*  Specifies which registers may be scratched by functions.    */
  63. int regscratch[MAXR+1]={0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
  64.                           0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  65.                           1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
  66.                           0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  67.                           1,1,0,0,0,1,1,1,1};
  68.  
  69. struct reg_handle empty_reg_handle={0,0};
  70.  
  71. /* Names of target-specific variable attributes.                */
  72. char *g_attr_name[]={"__far","__near","__chip","__saveds",0};
  73.  
  74. /****************************************/
  75. /*  Private data and functions.         */
  76. /****************************************/
  77.  
  78. static char *mregnames[MAXR+1];
  79.  
  80. static long malign[16]=  {1,1,2,4,4,4,4,1,4,1,1,1,4,1};
  81. static long msizetab[16]={1,1,2,4,4,4,8,0,4,0,0,0,4,0};
  82.  
  83. static struct Typ ltyp={LONG},ldbl={DOUBLE},lchar={CHAR};
  84.  
  85. static int r0=1;                   /*  special register                    */
  86. static int r2=3;                   /*  reserved or toc                     */
  87. static int r3=11;                  /*  return value                        */
  88. static int sp=2;                   /*  Stackpointer                        */
  89. static int fp=2;                   /*  Framepointer                        */
  90. static int sd=14;                  /*  SmallDataPointer                    */
  91. static int t1=12,t2=13,t3=1;       /*  Temporaries used by code generator  */
  92. static int f1=33,f2=34,f3=35;      /*  Temporaries used by code generator  */
  93. static int cr0=65;                 /*  Default condition-code-register     */
  94.  
  95. #define DATA 0
  96. #define BSS 1
  97. #define CODE 2
  98. #define RODATA 3
  99. #define TOC 4
  100.  
  101. static int lastlabel;
  102.  
  103. static int section=-1,newobj,crsave;
  104. static char *codename="\t.text\n",*dataname="\t.data\n",*bssname="",
  105.   *rodataname="\t.section\t.rodata\n",*tocname="\t.tocd\n";
  106. static int is_const(struct Typ *);
  107. static char *labprefix="l",*idprefix="_",*tocprefix="@_";
  108. static long frameoffset,pushed,maxpushed,framesize,localoffset,minframe=8;
  109. static void probj2(FILE *f,struct obj *p,int t);
  110.  
  111. struct StatFPtrList {
  112.   struct StatFPtrList *next;
  113.   struct Var *vptr;
  114. };
  115. static struct StatFPtrList *firstfptr = NULL;
  116.  
  117.  
  118. static long real_offset(struct obj *o)
  119. {
  120.   long off;
  121.   if(zl2l(o->v->offset)>=0){
  122.      return zl2l(o->v->offset)+frameoffset+zl2l(o->val.vlong);
  123.   }else{
  124.     return framesize+minframe-zl2l(o->v->offset)-zl2l(maxalign)+zl2l(o->val.vlong);
  125.   }
  126. }
  127. static long hi(long off)
  128. {
  129.   zlong zl=l2zl(off),r=zlrshift(zl,l2zl(16L));
  130.   if(!zleqto(zland(zl,l2zl(32768L)),l2zl(0L))) r=zladd(r,l2zl(1L));
  131.   return zl2l(zs2zl(zl2zs(zland(r,l2zl(65535L)))));
  132. }
  133. static long lo(long off)
  134. {
  135.   return zl2l(zs2zl(zl2zs(zland(l2zl(off),l2zl(65535L)))));
  136. }
  137. static struct fpconstlist {
  138.   struct fpconstlist *next;
  139.   int label,typ;
  140.   union atyps val;
  141. } *firstfpc;
  142.  
  143. static int addfpconst(struct obj *o,int t)
  144. {
  145.   struct fpconstlist *p=firstfpc;
  146.   t&=NQ;
  147.   if(g_flags[4]&USEDFLAG){
  148.     for(p=firstfpc;p;p=p->next){
  149.       if(t==p->typ){
  150.         eval_const(&p->val,t);
  151.         if(t==FLOAT&&zdeqto(vdouble,zf2zd(o->val.vfloat))) return p->label;
  152.         if(t==DOUBLE&&zdeqto(vdouble,o->val.vdouble)) return p->label;
  153.       }
  154.     }
  155.   }
  156.   p=mymalloc(sizeof(struct fpconstlist));
  157.   p->next=firstfpc;
  158.   p->label=++label;
  159.   p->typ=t;
  160.   p->val=o->val;
  161.   firstfpc=p;
  162.   return p->label;
  163. }
  164.  
  165. #define REG_IND 1
  166. #define IMM_IND 2
  167. #define UPDATE  64
  168.  
  169. static struct obj *cam(int flags,int base,long offset)
  170. /*  Initializes an addressing-mode structure and returns a pointer to   */
  171. /*  that object. Will not survive a second call!                        */
  172. {
  173.   static struct obj obj;
  174.   static struct AddressingMode am;
  175.   obj.am=&am;
  176.   am.flags=flags;
  177.   am.base=base;
  178.   am.offset=offset;
  179.   return &obj;
  180. }
  181.  
  182. static char *ldt[]={"","bz","ha","wz","wz","fs","fd","","wz","","","","","","","",
  183.                     "","bz","hz","wz","wz"};
  184. static char *sdt[]={"","b","h","w","w","fs","fd","","w","","","","","","","",
  185.                     "","b","h","w","w"};
  186.  
  187. static int use_sd(int t)
  188. /*  Shall the object of type t be addressed in small-data-mode?  */
  189. {
  190.   if(g_flags[3]&USEDFLAG) return 1;
  191.   if((g_flags[13]&USEDFLAG)&&(t&NQ)<=POINTER) return 1;
  192.   return 0;
  193. }
  194.  
  195. static void load_address(FILE *f,int r,struct obj *o,int typ)
  196. /*  Generates code to load the address of a variable into register r.   */
  197. {
  198.   if(!(o->flags&VAR)) ierror(0);
  199.   if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
  200.     long off=real_offset(o);
  201.     if(off<=32767){
  202.       fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[sp],off);
  203.     }else{
  204.       fprintf(f,"\taddis\t%s,%s,%ld\n",mregnames[r],mregnames[sp],hi(off));
  205.       fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[r],lo(off));
  206.     }
  207.   }else{
  208.     if(use_sd(o->v->vtyp->flags)&&!(o->v->tattr&1)){
  209.       fprintf(f,"\tla\t%s,",mregnames[r]);
  210.       probj2(f,o,typ);fprintf(f,"(%s)\n",mregnames[sd]);
  211.     }else{
  212.       if(g_flags[12]&USEDFLAG){
  213.         zlong offset=o->val.vlong;
  214.         if((o->v->vtyp->flags&NQ)==FUNKT&&o->v->storage_class==STATIC){
  215.           /* check if static function pointer was already created in TOC */
  216.           struct StatFPtrList **oldsfp=&firstfptr;
  217.           struct StatFPtrList *sfp=firstfptr;
  218.           while(sfp){
  219.             if(sfp->vptr==o->v) break;
  220.             oldsfp=&sfp->next;
  221.             sfp=sfp->next;
  222.           }
  223.           if(!sfp){
  224.             /* create new function pointer variable "@__fname" in TOC */
  225.             *oldsfp=sfp=mymalloc(sizeof(struct StatFPtrList));
  226.             sfp->next=NULL;
  227.             sfp->vptr=o->v;
  228.             fprintf(f,"%s\t.align\t2\n%s%s%s:\n\t.long\t%s%s\n%s",
  229.                     tocname,tocprefix,idprefix,o->v->identifier,
  230.                     idprefix,o->v->identifier,codename);
  231.           }
  232.         }
  233.         fprintf(f,"\tl%s\t%s,%s",ldt[LONG],mregnames[r],tocprefix);
  234.         o->val.vlong=l2zl(0L);probj2(f,o,POINTER);o->val.vlong=offset;
  235.         fprintf(f,"(%s)\n",mregnames[r2]);
  236.         if(hi(zl2l(offset))) fprintf(f,"\taddis\t%s,%s,%ld\n",mregnames[r],mregnames[r],hi(zl2l(offset)));
  237.         if(lo(zl2l(offset))) fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[r],lo(zl2l(offset)));
  238.       }else{
  239.         fprintf(f,"\tlis\t%s,",mregnames[r]);
  240.         probj2(f,o,typ);fprintf(f,"@ha\n");
  241.         fprintf(f,"\taddi\t%s,%s,",mregnames[r],mregnames[r]);
  242.         probj2(f,o,typ);fprintf(f,"@l\n");
  243.       }
  244.     }
  245.   }
  246. }
  247. static void load_reg(FILE *f,int r,struct obj *o,int typ,int tmp)
  248. /*  Generates code to load a memory object into register r. tmp is a    */
  249. /*  general purpose register which may be used. tmp can be r.           */
  250. {
  251.   typ&=NU;
  252.   if(o->flags&KONST){
  253.     long l;
  254.     eval_const(&o->val,typ);
  255.     if(typ==FLOAT||typ==DOUBLE){
  256.       int lab;
  257.       if((g_flags[5]&USEDFLAG)&&zdeqto(vdouble,d2zd(0.0))){
  258.         fprintf(f,"\tfsub\t%s,%s,%s\n",mregnames[r],mregnames[r],mregnames[r]);
  259.         return;
  260.       }
  261.       lab=addfpconst(o,typ);
  262.       if(use_sd(typ)){
  263.         fprintf(f,"\tl%s\t%s,%s%d(%s)\n",ldt[typ],mregnames[r],labprefix,lab,mregnames[sd]);
  264.       }else{
  265.         if(g_flags[12]&USEDFLAG){
  266.           fprintf(f,"\tl%s\t%s,%s%s%ld(%s)\n",ldt[LONG],mregnames[tmp],tocprefix,labprefix,(long)lab,mregnames[r2]);
  267.           fprintf(f,"\tl%s\t%s,0(%s)\n",ldt[typ],mregnames[r],mregnames[tmp]);
  268.         }else{
  269.           fprintf(f,"\tlis\t%s,%s%d@ha\n",mregnames[tmp],labprefix,lab);
  270.           fprintf(f,"\tl%s\t%s,%s%d@l(%s)\n",ldt[typ],mregnames[r],labprefix,lab,mregnames[tmp]);
  271.         }
  272.       }
  273.       return;
  274.     }
  275.     l=hi(zl2l(vlong));
  276.     if(l){
  277.       fprintf(f,"\tlis\t%s,%ld\n",mregnames[r],l);
  278.       l=lo(zl2l(vlong));
  279.       if(l) fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[r],l);
  280.     }else{
  281.       fprintf(f,"\tli\t%s,%ld\n",mregnames[r],zl2l(vlong));
  282.     }
  283.     return;
  284.   }
  285.   if((o->flags&VAR)&&(o->v->storage_class==EXTERN||o->v->storage_class==STATIC)){
  286.     if(o->flags&VARADR){
  287.       load_address(f,r,o,POINTER);
  288.     }else{
  289.       if(use_sd(o->v->vtyp->flags)&&!(o->v->tattr&1)){
  290.         fprintf(f,"\tl%s\t%s,",ldt[typ],mregnames[r]);
  291.         probj2(f,o,typ);fprintf(f,"(%s)\n",mregnames[sd]);
  292.       }else{
  293.         if(g_flags[12]&USEDFLAG){
  294.           zlong offset=o->val.vlong;
  295.           fprintf(f,"\tl%s\t%s,%s",ldt[LONG],mregnames[tmp],tocprefix);
  296.           o->val.vlong=l2zl(0L);probj2(f,o,POINTER);o->val.vlong=offset;
  297.           fprintf(f,"(%s)\n",mregnames[r2]);
  298.           if(hi(zl2l(offset))) fprintf(f,"\taddis\t%s,%s,%ld\n",mregnames[tmp],mregnames[tmp],hi(zl2l(offset)));
  299.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[typ],mregnames[r],lo(zl2l(offset)),mregnames[tmp]);
  300.         }else{
  301.           fprintf(f,"\tlis\t%s,",mregnames[tmp]);
  302.           probj2(f,o,typ);fprintf(f,"@ha\n");
  303.           fprintf(f,"\tl%s\t%s,",ldt[typ],mregnames[r]);
  304.           probj2(f,o,typ);fprintf(f,"@l(%s)\n",mregnames[tmp]);
  305.         }
  306.       }
  307.     }
  308.   }else{
  309.     if((o->flags&(DREFOBJ|REG))==REG){
  310.       if(r!=o->reg)
  311.         fprintf(f,"\t%smr\t%s,%s\n",r>=33?"f":"",mregnames[r],mregnames[o->reg]);
  312.     }else if(!o->am){
  313.       long off=real_offset(o);
  314.       if(off<=32767){
  315.         fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[typ],mregnames[r],off,mregnames[sp]);
  316.       }else{
  317.         fprintf(f,"\taddis\t%s,%s,%ld\n",mregnames[r],mregnames[sp],hi(off));
  318.         fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[typ],mregnames[r],lo(zl2l(off)),mregnames[r]);
  319.       }
  320.     }else{
  321.       fprintf(f,"\tl%s%s%s\t%s,",ldt[typ],(o->am->flags&UPDATE)?"u":"",(o->am->flags®_IND)?"x":"",mregnames[r]);
  322.       probj2(f,o,typ);fprintf(f,"\n");
  323.     }
  324.   }
  325.   if(typ==CHAR) fprintf(f,"\textsb\t%s,%s\n",mregnames[r],mregnames[r]);
  326. }
  327.  
  328. static void store_reg(FILE *f,int r,struct obj *o,int typ)
  329. /*  Generates code to store register r into memory object o.            */
  330. {
  331.   int tmp;
  332.   typ&=NQ;
  333.   if((o->flags&VAR)&&(o->v->storage_class==EXTERN||o->v->storage_class==STATIC)){
  334.     int tmp=t1;
  335.     if(tmp==r) tmp=t2;
  336.     if(use_sd(o->v->vtyp->flags)&&!(o->v->tattr&1)){
  337.       fprintf(f,"\tst%s\t%s,",sdt[typ],mregnames[r]);
  338.       probj2(f,o,typ);fprintf(f,"(%s)\n",mregnames[sd]);
  339.       return;
  340.     }else{
  341.       if(g_flags[12]&USEDFLAG){
  342.         zlong offset=o->val.vlong;
  343.         fprintf(f,"\tl%s\t%s,%s",ldt[LONG],mregnames[tmp],tocprefix);
  344.         o->val.vlong=l2zl(0L);probj2(f,o,POINTER);o->val.vlong=offset;
  345.         fprintf(f,"(%s)\n",mregnames[r2]);
  346.         if(hi(zl2l(offset))) fprintf(f,"\taddis\t%s,%s,%ld\n",mregnames[tmp],mregnames[tmp],hi(zl2l(offset)));
  347.         fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[typ],mregnames[r],lo(zl2l(offset)),mregnames[tmp]);
  348.         return;
  349.       }else{
  350.         fprintf(f,"\tlis\t%s,",mregnames[tmp]);
  351.         probj2(f,o,typ);fprintf(f,"@ha\n");
  352.         fprintf(f,"\tst%s\t%s,",sdt[typ],mregnames[r]);
  353.         probj2(f,o,typ);fprintf(f,"@l(%s)\n",mregnames[tmp]);
  354.         return;
  355.       }
  356.     }
  357.   }
  358.   if(!(o->flags&DREFOBJ)&&!o->am){
  359.     long off=real_offset(o);
  360.     if(r==t1) tmp=t2; else tmp=t1;
  361.     if(off<=32767){
  362.       fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[typ],mregnames[r],off,mregnames[sp]);
  363.     }else{
  364.       fprintf(f,"\taddis\t%s,%s,%ld\n",mregnames[tmp],mregnames[sp],hi(off));
  365.       fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[typ],mregnames[r],lo(off),mregnames[tmp]);
  366.     }
  367.   }else{
  368.     if(!o->am){
  369.       fprintf(f,"\tst%s\t%s,",sdt[typ],mregnames[r]);
  370.       probj2(f,o,typ);fprintf(f,"\n");
  371.     }else{
  372.       fprintf(f,"\tst%s%s%s\t%s,",sdt[typ],(o->am->flags&UPDATE)?"u":"",(o->am->flags®_IND)?"x":"",mregnames[r]);
  373.       probj2(f,o,typ);fprintf(f,"\n");
  374.     }
  375.   }
  376. }
  377.  
  378. static long pof2(zulong x)
  379. /*  Yields log2(x)+1 oder 0. */
  380. {
  381.   zulong p;int ln=1;
  382.   p=ul2zul(1L);
  383.   while(ln<=32&&zulleq(p,x)){
  384.     if(zuleqto(x,p)) return ln;
  385.     ln++;p=zuladd(p,p);
  386.   }
  387.   return 0;
  388. }
  389.  
  390. static char *dct[]={"","byte","uahalf","uaword","uaword","uaword","uaword"};
  391. static struct IC *do_refs(FILE *,struct IC *);
  392. static void pr(FILE *,struct IC *);
  393. static void function_top(FILE *,struct Var *,long);
  394. static void function_bottom(FILE *f,struct Var *,long);
  395.  
  396. #define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
  397.  
  398. static int q1reg,q2reg,zreg;
  399.  
  400. static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
  401. static char *logicals[]={"or","xor","and"};
  402. static char *record[]={"","."};
  403. static char *arithmetics[]={"slw","srw","add","sub","mullw","divw","mod"};
  404. static char *isimm[]={"","i"};
  405.  
  406. static struct IC *do_refs(FILE *f,struct IC *p)
  407. /*  Does some pre-processing like fetching operands from memory to      */
  408. /*  registers etc.                                                      */
  409. {
  410.   int typ=p->typf,typ1,reg,c=abs(p->code);
  411.  
  412.   if(c==CONVCHAR) typ=CHAR;
  413.   if(c==CONVUCHAR) typ=UNSIGNED|CHAR;
  414.   if(c==CONVSHORT) typ=SHORT;
  415.   if(c==CONVUSHORT) typ=UNSIGNED|SHORT;
  416.   if(c==CONVINT) typ=LONG;
  417.   if(c==CONVUINT) typ=UNSIGNED|LONG;
  418.   if(c==CONVLONG) typ=LONG;
  419.   if(c==CONVULONG) typ=UNSIGNED|LONG;
  420.   if(c==CONVFLOAT) typ=FLOAT;
  421.   if(c==CONVDOUBLE) typ=DOUBLE;
  422.   if(c==CONVPOINTER) typ=UNSIGNED|LONG;
  423.   if((typ&NQ)==POINTER) typ=UNSIGNED|LONG;
  424.  
  425.   if((c==SUB||c==SUBIFP)&&(p->q2.flags&(KONST|DREFOBJ))==KONST&&(typ&NQ)<=LONG){
  426.     eval_const(&p->q2.val,typ);
  427.     if(zlleq(vlong,l2zl(32768L))&&zlleq(l2zl(-32767L),vlong)){
  428.       union atyps val;
  429.       if(c==SUB){
  430.         if(p->code==SUB) p->code=c=ADD; else p->code=c=-ADD;
  431.       }else{
  432.         if(p->code==SUBIFP) p->code=c=ADDI2P; else p->code=c=-ADDI2P;
  433.       }
  434.       c=abs(c);
  435.       val.vlong=zlsub(l2zl(0L),vlong);
  436.       eval_const(&val,LONG);
  437.       insert_const2(&p->q2.val,typ);
  438.       p->typf=typ=(typ&~UNSIGNED);
  439.     }
  440.   }
  441.  
  442.   q1reg=q2reg=zreg=0;
  443.   if(p->q1.flags®) q1reg=p->q1.reg;
  444.   if(p->q2.flags®) q2reg=p->q2.reg;
  445.   if((p->z.flags&(REG|DREFOBJ))==REG) zreg=p->z.reg;
  446.  
  447.   if((p->q1.flags&(KONST|DREFOBJ))==KONST){
  448.     eval_const(&p->q1.val,typ);
  449.     if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f1; else reg=t1;
  450.     if(c==ASSIGN&&zreg) reg=zreg;
  451.     if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
  452.     if(c!=SUB||(typ&NQ)>LONG||!zlleq(vlong,l2zl(32767L))||!zlleq(l2zl(-32768L),vlong)){
  453.       load_reg(f,reg,&p->q1,typ,t1);
  454.       q1reg=reg;
  455.     }
  456.   }else if(c!=ADDRESS){
  457.     if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f1; else reg=t1;
  458.     if((c==ASSIGN||(c>=CONVCHAR&&c<=CONVULONG&&c!=CONVFLOAT&&c!=CONVDOUBLE))&&zreg>=1&&zreg<=32) reg=zreg;
  459.     if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
  460.     if(p->q1.am){
  461.       load_reg(f,reg,&p->q1,typ,t1);
  462.       q1reg=reg;
  463.     }else{
  464.       if(p->q1.flags&&!q1reg){
  465.         if(p->q1.flags&DREFOBJ) {typ1=POINTER;reg=t1;} else typ1=typ;
  466.         if((typ1&NQ)<=POINTER){
  467.           int m=p->q1.flags;
  468.           p->q1.flags&=~DREFOBJ;
  469.           load_reg(f,reg,&p->q1,typ1,t1);
  470.           p->q1.flags=m;
  471.           q1reg=reg;
  472.         }
  473.       }
  474.       if((p->q1.flags&DREFOBJ)&&(typ&NQ)<=POINTER){
  475.         if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f1; else reg=t1;
  476.         if((c==ASSIGN||(c>=CONVCHAR&&c<=CONVULONG&&c!=CONVFLOAT&&c!=CONVDOUBLE))&&zreg>=1&&zreg<=32) reg=zreg;
  477.         if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
  478.         if(p->q1.am)
  479.           load_reg(f,reg,&p->q1,typ,t1);
  480.         else
  481.           load_reg(f,reg,cam(IMM_IND,q1reg,0),typ,t1);
  482.         q1reg=reg;
  483.       }
  484.     }
  485.   }
  486.   typ=p->typf;
  487.   if((p->q2.flags&(KONST|DREFOBJ))==KONST){
  488.     eval_const(&p->q2.val,typ);
  489.     if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f2; else reg=t2;
  490.     if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE||c==DIV||c==SUB||c==MOD){
  491.       load_reg(f,reg,&p->q2,typ,t2);
  492.       q2reg=reg;
  493.     }else{
  494.       if((c>=OR&&c<=AND)||(c==COMPARE&&(typ&UNSIGNED))){
  495.         if(!zulleq(vulong,ul2zul(65535UL))){
  496.           load_reg(f,reg,&p->q2,typ,t2);
  497.           q2reg=reg;
  498.         }
  499.       }else{
  500.         if(!zlleq(vlong,l2zl(32767L))||!zlleq(l2zl(-32768L),vlong)){
  501.           load_reg(f,reg,&p->q2,typ,t2);
  502.           q2reg=reg;
  503.         }
  504.       }
  505.     }
  506.   }else{
  507.     if(p->q2.am){
  508.       if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f2; else reg=t2;
  509.       load_reg(f,reg,&p->q2,typ,t2);
  510.       q2reg=reg;
  511.     }else{
  512.       if(p->q2.flags&&!q2reg){
  513.         if((p->q2.flags&DREFOBJ)) typ1=POINTER; else typ1=typ;
  514.         if((typ1&NQ)==FLOAT||(typ1&NQ)==DOUBLE) reg=f2; else reg=t2;
  515.         if((typ1&NQ)<=POINTER){
  516.           int m=p->q2.flags;
  517.           p->q2.flags&=~DREFOBJ;
  518.           load_reg(f,reg,&p->q2,typ1,t2);
  519.           p->q2.flags=m;
  520.           q2reg=reg;
  521.         }
  522.       }
  523.       if((p->q2.flags&DREFOBJ)&&(typ&NQ)<=POINTER){
  524.         if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) reg=f2; else reg=t2;
  525.         if(p->q2.am)
  526.           load_reg(f,reg,&p->q2,typ,t2);
  527.         else
  528.           load_reg(f,reg,cam(IMM_IND,q2reg,0),typ,t2);
  529.         q2reg=reg;
  530.       }
  531.     }
  532.   }
  533.   if(p->z.am||(p->z.flags&&!isreg(z))){
  534.     typ=p->typf;
  535.     if((typ&NQ)==FLOAT||(typ&NQ)==DOUBLE) zreg=f3; else zreg=t3;
  536.   }
  537.   if(q1reg){ p->q1.flags=REG; p->q1.reg=q1reg;p->q1.am=0;}
  538.   if(q2reg){ p->q2.flags=REG; p->q2.reg=q2reg;p->q2.am=0;}
  539.   return p;
  540. }
  541. static void pr(FILE *f,struct IC *p)
  542.      /*  Writes the destination register to the real destination if necessary.   */
  543. {
  544.   int typ=p->typf;
  545.   if(p->code==ADDRESS) typ=POINTER;
  546.   if(p->z.flags){
  547.     if(p->z.am){
  548.       store_reg(f,zreg,&p->z,typ);
  549.     }else if(!isreg(z)){
  550.       if(p->z.flags&DREFOBJ){
  551.         if(p->z.flags®){
  552.           if(p->z.am)
  553.             store_reg(f,zreg,&p->z,typ);
  554.           else
  555.             store_reg(f,zreg,cam(IMM_IND,p->z.reg,0),typ);
  556.         }else{
  557.           int r;
  558.           if(t1==zreg) r=t2; else r=t1;
  559.           load_reg(f,r,&p->z,POINTER,r);
  560.           store_reg(f,zreg,cam(IMM_IND,r,0),typ);
  561.         }
  562.       }else{
  563.         store_reg(f,zreg,&p->z,typ);
  564.       }
  565.     }else{
  566.       if(p->z.reg!=zreg)
  567.         fprintf(f,"\t%smr\t%s,%s\n",zreg>=33?"f":"",mregnames[p->z.reg],mregnames[zreg]);
  568.     }
  569.   }
  570. }
  571.  
  572. static void probj2(FILE *f,struct obj *p,int t)
  573. /*  Prints an object.                               */
  574. {
  575.   if(p->am){
  576.     if(p->am->flags®_IND) fprintf(f,"%s,%s",mregnames[p->am->offset],mregnames[p->am->base]);
  577.     if(p->am->flags&IMM_IND) fprintf(f,"%ld(%s)",p->am->offset,mregnames[p->am->base]);
  578.     return;
  579.   }
  580.   /*  if(p->flags&DREFOBJ) fprintf(f,"(");*/
  581.   if(p->flags&VAR) {
  582.     if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
  583.       if(p->flags®){
  584.         fprintf(f,"%s",mregnames[p->reg]);
  585.       }else{
  586.         fprintf(f,"%ld(%s)",real_offset(p),mregnames[sp]);
  587.       }
  588.     }else{
  589.       if(!zleqto(l2zl(0L),p->val.vlong)){printval(f,&p->val,LONG,0);fprintf(f,"+");}
  590.       if(p->v->storage_class==STATIC&&(p->v->vtyp->flags&NQ)!=FUNKT){
  591.         fprintf(f,"%s%ld",labprefix,zl2l(p->v->offset));
  592.       }else{
  593.         fprintf(f,"%s%s",idprefix,p->v->identifier);
  594.       }
  595.     }
  596.   }
  597.   if((p->flags®)&&!(p->flags&VAR)) fprintf(f,"%s",mregnames[p->reg]);
  598.   if(p->flags&KONST){
  599.     printval(f,&p->val,t&NU,0);
  600.   }
  601.   /*  if(p->flags&DREFOBJ) fprintf(f,")");*/
  602. }
  603. static int exists_freereg(struct IC *p,int reg)
  604. /*  Test if there is a sequence of FREEREGs containing FREEREG reg. */
  605. {
  606.   while(p&&(p->code==FREEREG||p->code==ALLOCREG)){
  607.     if(p->code==FREEREG&&p->q1.reg==reg) return 1;
  608.     p=p->next;
  609.   }
  610.   return 0;
  611. }
  612.  
  613. static size_t lsize;
  614. static unsigned char *once,*twice;
  615.  
  616. static void peephole(struct IC *p)
  617. /* Try to use addressing modes */
  618. {
  619.   int c,c2,r,cnt;struct IC *p2;struct AddressingMode *am;
  620.   lsize=((label-lastlabel+1+7)/CHAR_BIT)*CHAR_BIT;
  621.   once=mymalloc(lsize);
  622.   twice=mymalloc(lsize);
  623.   memset(once,0,lsize);
  624.   memset(twice,0,lsize);
  625.   for(;p;p=p->next){
  626.     c=p->code;
  627.     /* Test which labels are jumped to more than once. */
  628.     if(c>=BEQ&&c<=BRA){
  629.       if(BTST(once,p->typf-lastlabel))
  630.         BSET(twice,p->typf-lastlabel);
  631.       else
  632.         BSET(once,p->typf-lastlabel);
  633.     }
  634.     /* Try test-opt */
  635.     if(c==TEST&&!(p->q1.flags&DREFOBJ)){
  636.       for(p2=p->prev;p2;p2=p2->prev){
  637.         c2=p2->code;
  638.         if(c2==NOP||c2==ALLOCREG||c2==FREEREG) continue;
  639.         if(c2==CALL||(c2>=LABEL&&c2<=BRA)) break;
  640.         if((p2->z.flags&DREFOBJ)&&(p->q1.flags&(REG|DREFOBJ))!=REG) break;
  641.         if(p->q1.flags==p2->z.flags&&p->q1.am==p2->z.am){
  642.           if(!(p->q1.flags&VAR)||(p->q1.v==p2->z.v&&zleqto(p->q1.val.vlong,p2->z.val.vlong))){
  643.             if(!(p->q1.flags®)||p->q1.reg==p2->z.reg){
  644.               if(p->z.flags==0||(isreg(z)&&p->z.reg==cr0)){
  645.                 if(p->typf==p2->typf&&(!(p->typf&UNSIGNED)||!multiple_ccs)){
  646.                   p2->code=-p2->code; /* mark it */
  647.                 }
  648.                 break;
  649.               }
  650.             }
  651.           }
  652.         }
  653.       }
  654.     }
  655.     /* Try update */
  656.     if((c==ADDI2P||c==SUBIFP)&&isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg){
  657.       if((p->q2.flags&(KONST|DREFOBJ))==KONST){
  658.         eval_const(&p->q2.val,p->typf);
  659.         if(c==SUBIFP) vlong=zlsub(l2zl(0L),vlong);
  660.         if(zlleq(l2zl(-32768L),vlong)&&zlleq(vlong,l2zl(32767L))){
  661.           struct obj *o;
  662.           r=p->q1.reg;cnt=0;o=0;
  663.           for(p2=p->next;p2;p2=p2->next){
  664.             c2=p2->code;
  665.             if(c2==NOP||c2==ALLOCREG||c2==FREEREG) continue;
  666.             if((c2==CALL&®scratch[r])||(c2>=LABEL&&c2<=BRA)) break;
  667.             if((p2->q1.flags&(DREFOBJ|REG))==REG&&p2->q1.reg==r) break;
  668.             if((p2->q2.flags&(DREFOBJ|REG))==REG&&p2->q2.reg==r) break;
  669.             if((p2->z.flags&(DREFOBJ|REG))==REG&&p2->z.reg==r) break;
  670.             if((p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){o=&p2->q1;cnt++;}
  671.             if((p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){o=&p2->q2;cnt++;}
  672.             if((p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){o=&p2->z;cnt++;}
  673.             if(cnt>1) break;
  674.             if(cnt==1){
  675.               if(p2->code==ASSIGN&&((p2->typf&NQ)>POINTER||!zleqto(p2->q2.val.vlong,sizetab[p2->typf&NQ])))
  676.                 break;
  677.               o->am=am=mymalloc(sizeof(*am));
  678.               o->am->flags=(IMM_IND|UPDATE);
  679.               o->am->base=r;
  680.               o->am->offset=zl2l(vlong);
  681.               p->code=NOP;
  682.               break;
  683.             }
  684.           }
  685.         }
  686.       }
  687.     }
  688.     /* Try const(reg) */
  689.     if((c==ADDI2P||c==SUBIFP)&&(p->q2.flags&(KONST|DREFOBJ))==KONST&&isreg(z)){
  690.       int base;zlong of;
  691.       p2=p->next;
  692.       while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
  693.       if(p2) c2=p2->code; else c2=0;
  694.       eval_const(&p->q2.val,p->typf);
  695.       if(c==SUBIFP) of=zlsub(l2zl(0L),vlong); else of=vlong;
  696.       r=p->z.reg;
  697.       if(isreg(q1)) base=p->q1.reg; else base=r;
  698.       if(c2&&zlleq(l2zl(-32768L),of)&&zlleq(of,l2zl(32767L))&&c2!=CALL&&(c2<LABEL||c2>BRA)
  699.          &&(c2!=ASSIGN||((p2->typf&NQ)<=POINTER&&zleqto(p2->q2.val.vlong,sizetab[p2->typf&NQ])))
  700.          &&c2!=ADDRESS&&(((p2->z.flags&(DREFOBJ|REG))==REG&&p2->z.reg==r&&p2->q2.flags==0)||exists_freereg(p2->next,r))){
  701.         if(((p2->q1.flags&(REG|DREFOBJ))!=REG||p2->q1.reg!=r)
  702.            &&((p2->q2.flags&(REG|DREFOBJ))!=REG||p2->q2.reg!=r)){
  703.           cnt=0;
  704.           if((p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
  705.             p2->q1.am=am=mymalloc(sizeof(*am));
  706.             p2->q1.am->flags=IMM_IND;
  707.             p2->q1.am->base=base;
  708.             p2->q1.am->offset=zl2l(of);
  709.             cnt++;
  710.           }
  711.           if((p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
  712.             p2->q2.am=am=mymalloc(sizeof(*am));
  713.             p2->q2.am->flags=IMM_IND;
  714.             p2->q2.am->base=base;
  715.             p2->q2.am->offset=zl2l(of);
  716.             cnt++;
  717.           }
  718.           if((p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
  719.             p2->z.am=am=mymalloc(sizeof(*am));
  720.             p2->z.am->flags=IMM_IND;
  721.             p2->z.am->base=base;
  722.             p2->z.am->offset=zl2l(of);
  723.             cnt++;
  724.           }
  725.           if(isreg(q1)){
  726.             p->code=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
  727.           }else{
  728.             p->code=ASSIGN;p->q2.flags=0;
  729.           }
  730.           if(cnt==1&&((p2->q1.flags&(DREFOBJ|REG))!=REG||p2->q1.reg!=base)
  731.              &&((p2->q2.flags&(DREFOBJ|REG))!=REG||p2->q2.reg!=base)
  732.              &&((p2->z.flags&(DREFOBJ|REG))!=REG||p2->z.reg!=base) ){
  733.             /* Can we use update? */
  734.             p2=p2->next;
  735.             while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
  736.             if(p2){
  737.               c2=p2->code;
  738.               if(c2==ADDI2P||c2==SUBIFP){
  739.                 if((p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==base
  740.                    &&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==base
  741.                    &&(p2->q2.flags&(KONST|DREFOBJ))==KONST ){
  742.                   eval_const(&p2->q2.val,p2->typf);
  743.                   if(c2==SUBIFP) vlong=zlsub(l2zl(0L),vlong);
  744.                   if(zleqto(vlong,of)){
  745.                     am->flags|=UPDATE;
  746.                     p2->code=NOP;
  747.                   }
  748.                 }
  749.               }
  750.             }
  751.           }
  752.           continue;
  753.         }
  754.       }
  755.     }
  756.     /* Try reg,reg */
  757.     if(c==ADDI2P&&isreg(q2)&&isreg(z)&&p->q2.reg!=p->z.reg){
  758.       int base,idx;
  759.       p2=p->next;
  760.       while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
  761.       if(p2) c2=p2->code; else c2=0;
  762.       r=p->z.reg;idx=p->q2.reg;
  763.       if(isreg(q1)) base=p->q1.reg; else base=r;
  764.       if(c2&&c2!=CALL&&(c2<LABEL||c2>BRA)
  765.          &&(c2!=ASSIGN||((p2->typf&NQ)<=POINTER&&zleqto(p2->q2.val.vlong,sizetab[p2->typf&NQ])))
  766.          &&c2!=ADDRESS&&exists_freereg(p2->next,r)){
  767.         if(((p2->q1.flags&(REG|DREFOBJ))!=REG||p2->q1.reg!=r)
  768.            &&((p2->q2.flags&(REG|DREFOBJ))!=REG||p2->q2.reg!=r) ){
  769.           cnt=0;
  770.           if((p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
  771.             p2->q1.am=am=mymalloc(sizeof(*am));
  772.             p2->q1.am->flags=REG_IND;
  773.             p2->q1.am->base=base;
  774.             p2->q1.am->offset=idx;
  775.             cnt++;
  776.           }
  777.           if((p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
  778.             p2->q2.am=am=mymalloc(sizeof(*am));
  779.             p2->q2.am->flags=REG_IND;
  780.             p2->q2.am->base=base;
  781.             p2->q2.am->offset=idx;
  782.             cnt++;
  783.           }
  784.           if((p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
  785.             p2->z.am=am=mymalloc(sizeof(*am));
  786.             p2->z.am->flags=REG_IND;
  787.             p2->z.am->base=base;
  788.             p2->z.am->offset=idx;
  789.             cnt++;
  790.           }
  791.           if(isreg(q1)){
  792.             p->code=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
  793.           }else{
  794.             p->code=ASSIGN;p->q2.flags=0;
  795.           }
  796.           if(cnt==1&&((p2->q1.flags&(DREFOBJ|REG))!=REG||p2->q1.reg!=base)
  797.              &&((p2->q2.flags&(DREFOBJ|REG))!=REG||p2->q2.reg!=base)
  798.              &&((p2->z.flags&(DREFOBJ|REG))!=REG||p2->z.reg!=base) ){
  799.             /* Can we use update? */
  800.             p2=p2->next;
  801.             while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
  802.             if(p2){
  803.               c2=p2->code;
  804.               if(c2==ADDI2P){
  805.                 if((p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==base
  806.                    &&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==base
  807.                    &&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==idx){
  808.                   am->flags|=UPDATE;
  809.                   p2->code=NOP;
  810.                 }
  811.               }
  812.             }
  813.           }
  814.           continue;
  815.         }
  816.       }
  817.     }
  818.   }
  819. }
  820.  
  821. static void toc_entry(FILE *f,struct Var *v)
  822. /*  Create a toc-entry.  */
  823. {
  824.   if(!use_sd(v->vtyp->flags)||(v->tattr&1)){
  825.     if(v->storage_class==STATIC&&(v->vtyp->flags&NQ)!=FUNKT){
  826.       fprintf(f,"\t.tocd\n");
  827.       fprintf(f,"%s%s%ld:\n",tocprefix,labprefix,zl2l(v->offset));
  828.       fprintf(f,"\t.long\t%s%ld\n",labprefix,zl2l(v->offset));
  829.     }else{
  830.       if ((v->vtyp->flags&NQ)!=FUNKT){
  831.         fprintf(f,"\t.tocd\n");
  832.         fprintf(f,"%s%s%s:\n",tocprefix,idprefix,v->identifier);
  833.         fprintf(f,"\t.long\t%s%s\n",idprefix,v->identifier);
  834.       }
  835.       if(v->storage_class==EXTERN)
  836.         fprintf(f,"\t.global\t%s%s%s\n",tocprefix,idprefix,v->identifier);
  837.     }
  838.     section=TOC;
  839.   }
  840. }
  841.  
  842. static int stmw,stme;
  843.  
  844. static void function_top(FILE *f,struct Var *v,long offset)
  845. /*  Generates function top.                             */
  846. {
  847.   int i,preg;long of;
  848.   if(g_flags[12]&USEDFLAG) toc_entry(f,v);
  849.   if(mregnames[1]!=regnames[1]) fprintf(f,"#vsc elf\n");
  850.   if(g_flags[0]&USEDFLAG) fprintf(f,"#vsc cpu %s\n",g_flags_val[0].p);
  851.   if(g_flags[1]&USEDFLAG) fprintf(f,"#vsc fpu %s\n",g_flags_val[1].p);
  852.   if(section!=CODE){fprintf(f,codename);section=CODE;}
  853.   fprintf(f,"\t.sdreg\t%s\n",mregnames[sd]);
  854.   if(v->storage_class==EXTERN) fprintf(f,"\t.global\t%s%s\n",idprefix,v->identifier);
  855.   fprintf(f,"\t.align\t4\n%s%s:\n",idprefix,v->identifier);
  856.   frameoffset=minframe+maxpushed;
  857.   framesize=frameoffset+offset;
  858.   stmw=0;stme=0;
  859.   for(i=1;i<=64;i++){
  860.     if((i==sd&&(v->tattr&8))||(regused[i]&&!regscratch[i]&&!regsa[i])){
  861.       if(i<=32) framesize+=4; else framesize+=8;
  862.       if(stmw||(regnames[i][0]=='r'&®names[i][1]=='3'&®names[i][2]=='1'))
  863.         stmw=i;
  864.     }else{
  865.       if(stmw){ stme=stmw;stmw=0;}
  866.     }
  867.   }
  868.   if(!(g_flags[11]&USEDFLAG)) stme=0;
  869.   for(crsave=0,i=65;i<=72;i++)
  870.     if(regused[i]&&!regscratch[i]&&!regsa[i]) crsave=1;
  871.   if(crsave&&!(g_flags[12]&USEDFLAG)) framesize+=4;
  872.   if(framesize==minframe&&function_calls==0&&!crsave) framesize=frameoffset=0;
  873.   framesize=(framesize+15)/16*16;
  874.   if(function_calls){
  875.     if(g_flags[12]&USEDFLAG)
  876.       fprintf(f,"\tmflr\t%s\n\tst%s\t%s,8(%s)\n",mregnames[t1],sdt[LONG],mregnames[t1],mregnames[sp]);
  877.     else
  878.       fprintf(f,"\tmflr\t%s\n\tst%s\t%s,4(%s)\n",mregnames[t1],sdt[LONG],mregnames[t1],mregnames[sp]);
  879.   }
  880.   of=minframe+maxpushed+offset;
  881.   if(framesize!=0){
  882.     if(framesize<=32767){
  883.       fprintf(f,"\tstwu\t%s,-%ld(%s)\n",mregnames[sp],framesize,mregnames[sp]);
  884.       preg=sp;
  885.     }else{
  886.       fprintf(f,"\tmr\t%s,%s\n",mregnames[t2],mregnames[sp]);
  887.       fprintf(f,"\tlis\t%s,%ld\n",mregnames[t1],hi(-framesize));
  888.       fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[t1],mregnames[t1],lo(-framesize));
  889.       fprintf(f,"\tstwux\t%s,%s,%s\n",mregnames[sp],mregnames[sp],mregnames[t1]);
  890.       preg=t2;of-=framesize;
  891.     }
  892.   }
  893.   if(crsave){
  894.     if(g_flags[12]&USEDFLAG){
  895.       fprintf(f,"\tmfcr\t%s\n\tst%s\t%s,4(%s)\n",mregnames[t1],sdt[LONG],mregnames[t1],mregnames[preg]);
  896.     }else{
  897.       fprintf(f,"\tmfcr\t%s\n\tst%s\t%s,%ld(%s)\n",mregnames[t1],sdt[LONG],mregnames[t1],of,mregnames[preg]);
  898.       of+=4;
  899.     }
  900.   }
  901.   for(i=1;i<=64;i++){
  902.     if((i==sd&&(v->tattr&8))||(regused[i]&&!regscratch[i]&&!regsa[i])){
  903.       if(i<=32){
  904.         if(stme&&stme!=i&®names[i][1]=='3'&®names[i][2]=='1'){
  905.           fprintf(f,"\tstmw\t%s,%ld(%s)\n",mregnames[stme],of,mregnames[preg]);
  906.           of+=(stme-i+1)*4;
  907.           i=stme;
  908.         }else{
  909.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[LONG],mregnames[i],of,mregnames[preg]);
  910.           of+=4;
  911.         }
  912.       }else{
  913.         fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[DOUBLE],mregnames[i],of,mregnames[preg]);
  914.         of+=8;
  915.       }
  916.     }
  917.   }
  918.   if(v->tattr&8){
  919.     if(g_flags[12]&USEDFLAG){
  920.       fprintf(f,"\t.global\t%s__getr2\n",idprefix);
  921.       if(!function_calls)
  922.         fprintf(f,"\tmflr\t%s\n",mregnames[t2]);
  923.       fprintf(f,"\tbl\t%s__getr2\n",idprefix);
  924.       if(!function_calls)
  925.         fprintf(f,"\tmtlr\t%s\n",mregnames[t2]);
  926.     }else{
  927.       fprintf(f,"\tlis\t%s,%s_LinkerDB@ha\n",mregnames[sd],idprefix);
  928.       fprintf(f,"\taddi\t%s,%s,%s_LinkerDB@l\n",mregnames[sd],mregnames[sd],idprefix);
  929.     }
  930.   }
  931. }
  932. static void function_bottom(FILE *f,struct Var *v,long offset)
  933. /*  Generates function bottom.                          */
  934. {
  935.   int i,preg;long of;
  936.   of=minframe+maxpushed+offset;
  937.   if(framesize<=32767){
  938.     preg=sp;
  939.   }else{
  940.     fprintf(f,"\tlwz\t%s,0(%s)\n",mregnames[t2],mregnames[sp]);
  941.     preg=t2;of-=framesize;
  942.   }
  943.   if(crsave){
  944.     if(g_flags[12]&USEDFLAG){
  945.       fprintf(f,"\tl%s\t%s,8(%s)\n\tmtcr\t%s\n",ldt[LONG],mregnames[t1],mregnames[preg],mregnames[t1]);
  946.     }else{
  947.       fprintf(f,"\tl%s\t%s,%ld(%s)\n\tmtcr\t%s\n",ldt[LONG],mregnames[t1],of,mregnames[preg],mregnames[t1]);
  948.       of+=4;
  949.     }
  950.   }
  951.   for(i=1;i<=64;i++){
  952.     if((i==sd&&(v->tattr&8))||(regused[i]&&!regscratch[i]&&!regsa[i])){
  953.       if(i<=32){
  954.         if(stme&&stme!=i&®names[i][1]=='3'&®names[i][2]=='1'){
  955.           fprintf(f,"\tlmw\t%s,%ld(%s)\n",mregnames[stme],of,mregnames[preg]);
  956.           of+=(stme-i+1)*4;
  957.           i=stme;
  958.         }else{
  959.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[LONG],mregnames[i],of,mregnames[preg]);
  960.           of+=4;
  961.         }
  962.       }else{
  963.         fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[DOUBLE],mregnames[i],of,mregnames[preg]);
  964.         of+=8;
  965.       }
  966.     }
  967.   }
  968.   if(framesize){
  969.     if(framesize<=32767)
  970.       fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[sp],mregnames[sp],framesize);
  971.     else
  972.       fprintf(f,"\tmr\t%s,%s\n",mregnames[sp],mregnames[preg]);
  973.   }
  974.   if(function_calls){
  975.     if(g_flags[12]&USEDFLAG)
  976.       fprintf(f,"\tl%s\t%s,8(%s)\n\tmtlr\t%s\n",ldt[LONG],mregnames[t1],mregnames[sp],mregnames[t1]);
  977.     else
  978.       fprintf(f,"\tl%s\t%s,4(%s)\n\tmtlr\t%s\n",ldt[LONG],mregnames[t1],mregnames[sp],mregnames[t1]);
  979.   }
  980.   fprintf(f,"\tblr\n");
  981.   fprintf(f,"\t.type\t%s%s,@function\n",idprefix,v->identifier);
  982.   fprintf(f,"\t.size\t%s%s,$-%s%s\n",idprefix,v->identifier,idprefix,v->identifier);
  983. }
  984. static int is_const(struct Typ *t)
  985. /*  Tests if a type can be placed in the code-section.  */
  986. {
  987.     if(!(t->flags&(CONST|STRINGCONST))){
  988.         do{
  989.             if(t->flags&(CONST|STRINGCONST)) return 1;
  990.             if((t->flags&NQ)!=ARRAY) return 0;
  991.             t=t->next;
  992.         }while(1);
  993.     }else return 1;
  994. }
  995. static int balign(struct obj *o)
  996. /*  Liefert die unteren 2 Bits des Objekts. -1 wenn unklar. */
  997. {
  998.   int sc;
  999.   if(o->flags&DREFOBJ) return -1;
  1000.   if(o->am) ierror(0);
  1001.   if(!(o->flags&VAR)) ierror(0);
  1002.   sc=o->v->storage_class;
  1003.   if(sc==EXTERN||sc==STATIC){
  1004.     /* Alle statischen Daten werden vom cg auf 32bit alignt. */
  1005.     return zl2l(zland(o->val.vlong,l2zl(3L)));
  1006.   }
  1007.   if(sc==AUTO||sc==REGISTER){
  1008.     zlong of=o->v->offset;
  1009.     if(!zlleq(l2zl(0L),of))
  1010.       of=zlsub(l2zl(0L),zladd(of,maxalign));
  1011.     return zl2l(zland(zladd(of,o->val.vlong),l2zl(3L)));
  1012.   }
  1013.   ierror(0);
  1014. }
  1015.  
  1016. /****************************************/
  1017. /*  End of private data and functions.  */
  1018. /****************************************/
  1019.  
  1020.  
  1021. int init_cg(void)
  1022. /*  Does necessary initializations for the code-generator. Gets called  */
  1023. /*  once at the beginning and should return 0 in case of problems.      */
  1024. {
  1025.   int i;
  1026.   /*  Initialize some values which cannot be statically initialized   */
  1027.   /*  because they are stored in the target's arithmetic.             */
  1028.   maxalign=l2zl(4L);
  1029.   char_bit=l2zl(8L);
  1030.   if(g_flags[7]&USEDFLAG){
  1031.     malign[INT]=malign[LONG]=malign[POINTER]=malign[FLOAT]=malign[DOUBLE]=2;
  1032.   }
  1033.   for(i=0;i<16;i++){
  1034.     sizetab[i]=l2zl(msizetab[i]);
  1035.     align[i]=l2zl(malign[i]);
  1036.   }
  1037.   for(i=0;i<=MAXR;i++) mregnames[i]=regnames[i];
  1038.   for(i= 1;i<=32;i++){
  1039.     regsize[i]=l2zl(4L);
  1040.     regtype[i]=<yp;
  1041.     if(g_flags[8]&USEDFLAG) mregnames[i]++;
  1042.   }
  1043.   for(i=33;i<=64;i++){
  1044.     regsize[i]=l2zl(8L);
  1045.     regtype[i]=&ldbl;
  1046.     if(g_flags[8]&USEDFLAG) mregnames[i]++;
  1047.   }
  1048.   for(i=65;i<=72;i++){
  1049.     regsize[i]=l2zl(1L);
  1050.     regtype[i]=&lchar;
  1051.     if(g_flags[8]&USEDFLAG) mregnames[i]+=2;
  1052.   }
  1053.  
  1054.   /*  Use multiple ccs.   */
  1055.   multiple_ccs=1;
  1056.  
  1057.   /*  Initialize the min/max-settings. Note that the types of the     */
  1058.   /*  host system may be different from the target system and you may */
  1059.   /*  only use the smallest maximum values ANSI guarantees if you     */
  1060.   /*  want to be portable.                                            */
  1061.   /*  That's the reason for the subtraction in t_min[INT]. Long could */
  1062.   /*  be unable to represent -2147483648 on the host system.          */
  1063.   t_min[UNSIGNED|CHAR]=t_min[UNSIGNED|SHORT]=t_min[UNSIGNED|INT]=t_min[UNSIGNED|LONG]=l2zl(0L);
  1064.   t_min[CHAR]=l2zl(-128L);
  1065.   t_min[SHORT]=l2zl(-32768L);
  1066.   t_min[INT]=zlsub(l2zl(-2147483647L),l2zl(1L));
  1067.   t_min[LONG]=t_min[INT];
  1068.   t_max[CHAR]=ul2zul(127UL);
  1069.   t_max[SHORT]=ul2zul(32767UL);
  1070.   t_max[INT]=ul2zul(2147483647UL);
  1071.   t_max[LONG]=t_max[INT];
  1072.   t_max[UNSIGNED|CHAR]=ul2zul(255UL);
  1073.   t_max[UNSIGNED|SHORT]=ul2zul(65535UL);
  1074.   t_max[UNSIGNED|INT]=ul2zul(4294967295UL);
  1075.   t_max[UNSIGNED|LONG]=t_max[UNSIGNED|INT];
  1076.   /*  Reserve a few registers for use by the code-generator.      */
  1077.   /*  This is not optimal but simple.                             */
  1078.   if(g_flags[12]&USEDFLAG) sd=r2;
  1079.   regsa[t1]=regsa[t2]=regsa[t3]=1;
  1080.   regsa[f1]=regsa[f2]=regsa[f3]=1;
  1081.   regsa[sp]=regsa[fp]=regsa[sd]=regsa[r2]=1;
  1082.   regscratch[t1]=regscratch[t2]=regscratch[t3]=0;
  1083.   regscratch[f1]=regscratch[f2]=regscratch[f3]=0;
  1084.   regscratch[sp]=regscratch[fp]=regscratch[sd]=regscratch[r2]=0;
  1085.  
  1086.   if(g_flags[6]&USEDFLAG) {minframe=8;labprefix=".l";idprefix="";}
  1087.   if(g_flags[12]&USEDFLAG) {minframe=24;labprefix="l";idprefix="_";}
  1088.  
  1089.   return 1;
  1090. }
  1091.  
  1092. int freturn(struct Typ *t)
  1093. /*  Returns the register in which variables of type t are returned. */
  1094. /*  If the value cannot be returned in a register returns 0.        */
  1095. /*  A pointer MUST be returned in a register. The code-generator    */
  1096. /*  has to simulate a pseudo register if necessary.                 */
  1097. {
  1098.     if((t->flags&NQ)==FLOAT||(t->flags&NQ)==DOUBLE) return 46;
  1099.     if((t->flags&NQ)==STRUCT||(t->flags&NQ)==UNION) return 0;
  1100.     if(zlleq(szof(t),l2zl(4L))) return(r3); else return 0;
  1101. }
  1102.  
  1103. int regok(int r,int t,int mode)
  1104. /*  Returns 0 if register r cannot store variables of   */
  1105. /*  type t. If t==POINTER and mode!=0 then it returns   */
  1106. /*  non-zero only if the register can store a pointer   */
  1107. /*  and dereference a pointer to mode.                  */
  1108. {
  1109.     if(r==0) return 0;
  1110.     t&=NQ;
  1111.     if(t==0){
  1112.         if(r>=65&&r<=72) return 1; else return 0;
  1113.     }
  1114.     if((t==FLOAT||t==DOUBLE)&&r>=33&&r<=64) return 1;
  1115.     if(t==POINTER&&r>=1&&r<=32) return 1;
  1116.     if(t>=CHAR&&t<=LONG&&r>=1&&r<=32) return 1;
  1117.     return 0;
  1118. }
  1119.  
  1120. int dangerous_IC(struct IC *p)
  1121. /*  Returns zero if the IC p can be safely executed     */
  1122. /*  without danger of exceptions or similar things.     */
  1123. /*  vbcc may generate code in which non-dangerous ICs   */
  1124. /*  are sometimes executed although control-flow may    */
  1125. /*  never reach them (mainly when moving computations   */
  1126. /*  out of loops).                                      */
  1127. /*  Typical ICs that generate exceptions on some        */
  1128. /*  machines are:                                       */
  1129. /*      - accesses via pointers                         */
  1130. /*      - division/modulo                               */
  1131. /*      - overflow on signed integer/floats             */
  1132. {
  1133.     int c=p->code;
  1134.     if((p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ)||(p->z.flags&DREFOBJ))
  1135.         return 0;
  1136.     if((c==DIV||c==MOD)&&!(p->q2.flags&KONST))
  1137.         return 1;
  1138.     return 0;
  1139. }
  1140.  
  1141. int must_convert(np p,int t)
  1142. /*  Returns zero if code for converting np to type t    */
  1143. /*  can be omitted.                                     */
  1144. /*  On the PowerPC cpu pointers and 32bit               */
  1145. /*  integers have the same representation and can use   */
  1146. /*  the same registers.                                 */
  1147. {
  1148.     int o=p->ntyp->flags,op=o&NQ,tp=t&NQ;
  1149.     if((op==INT||op==LONG||op==POINTER)&&(tp==INT||tp==LONG||tp==POINTER))
  1150.       return 0;
  1151.     return 1;
  1152. }
  1153.  
  1154. void gen_ds(FILE *f,zlong size,struct Typ *t)
  1155. /*  This function has to create <size> bytes of storage */
  1156. /*  initialized with zero.                              */
  1157. {
  1158.     if(newobj&§ion!=TOC) fprintf(f,"%ld\n",zl2l(size));
  1159.         else   fprintf(f,"\t.space\t%ld\n",zl2l(size));
  1160.     newobj=0;
  1161. }
  1162.  
  1163. void gen_align(FILE *f,zlong align)
  1164. /*  This function has to make sure the next data is     */
  1165. /*  aligned to multiples of <align> bytes.              */
  1166. {
  1167.     fprintf(f,"\t.align\t2\n");
  1168. }
  1169.  
  1170. void gen_var_head(FILE *f,struct Var *v)
  1171. /*  This function has to create the head of a variable  */
  1172. /*  definition, i.e. the label and information for      */
  1173. /*  linkage etc.                                        */
  1174. {
  1175.   int constflag;
  1176.   if(v->clist) constflag=is_const(v->vtyp);
  1177.   if(v->storage_class==STATIC){
  1178.     if((v->vtyp->flags&NQ)==FUNKT) return;
  1179.     if(use_sd(v->vtyp->flags)&&!(v->tattr&1)){
  1180.       if(section!=TOC){fprintf(f,tocname);section=TOC;}
  1181.     }else{
  1182.       if(g_flags[12]&USEDFLAG) toc_entry(f,v);
  1183.       if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  1184.       if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&§ion!=RODATA){fprintf(f,rodataname);section=RODATA;}
  1185.       if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  1186.     }
  1187.     fprintf(f,"\t.type\t%s%ld,@object\n",labprefix,zl2l(v->offset));
  1188.     fprintf(f,"\t.size\t%s%ld,%ld\n",labprefix,zl2l(v->offset),zl2l(szof(v->vtyp)));
  1189.     if(v->clist||section==TOC)
  1190.       fprintf(f,"%s%ld:\n",labprefix,zl2l(v->offset));
  1191.     else
  1192.       fprintf(f,"\t.lcomm\t%s%ld,",labprefix,zl2l(v->offset));
  1193.     newobj=1;
  1194.   }
  1195.   if(v->storage_class==EXTERN){
  1196.     fprintf(f,"\t.global\t%s%s\n",idprefix,v->identifier);
  1197.     if((g_flags[12]&USEDFLAG)&&(!use_sd(v->vtyp->flags)||(v->tattr&1)))
  1198.       fprintf(f,"\t.global\t%s%s%s\n",tocprefix,idprefix,v->identifier);
  1199.     if(v->flags&(DEFINED|TENTATIVE)){
  1200.       if(use_sd(v->vtyp->flags)&&!(v->tattr&1)){
  1201.         if(section!=TOC){fprintf(f,tocname);section=TOC;}
  1202.       }else{
  1203.         if(g_flags[12]&USEDFLAG) toc_entry(f,v);
  1204.         if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  1205.         if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&§ion!=RODATA){fprintf(f,rodataname);section=RODATA;}
  1206.         if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  1207.       }
  1208.       fprintf(f,"\t.type\t%s%s,@object\n",idprefix,v->identifier);
  1209.       fprintf(f,"\t.size\t%s%s,%ld\n",idprefix,v->identifier,zl2l(szof(v->vtyp)));
  1210.       if(v->clist||section==TOC)
  1211.         fprintf(f,"%s%s:\n",idprefix,v->identifier);
  1212.       else
  1213.         fprintf(f,"\t.comm\t%s%s,",idprefix,v->identifier);
  1214.       newobj=1;
  1215.     }
  1216.   }
  1217. }
  1218.  
  1219. void gen_dc(FILE *f,int t,struct const_list *p)
  1220. /*  This function has to create static storage          */
  1221. /*  initialized with const-list p.                      */
  1222. {
  1223.     if((t&NQ)==POINTER) t=UNSIGNED|LONG;
  1224.     fprintf(f,"\t.%s\t",dct[t&NQ]);
  1225.     if(!p->tree){
  1226.         if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  1227.         /*  auch wieder nicht sehr schoen und IEEE noetig   */
  1228.             unsigned char *ip;
  1229.             ip=(unsigned char *)&p->val.vdouble;
  1230.             fprintf(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
  1231.             if((t&NQ)==DOUBLE){
  1232.                 fprintf(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
  1233.             }
  1234.         }else{
  1235.             printval(f,&p->val,t&NU,0);
  1236.         }
  1237.     }else{
  1238.         probj2(f,&p->tree->o,t&NU);
  1239.     }
  1240.     fprintf(f,"\n");newobj=0;
  1241. }
  1242.  
  1243.  
  1244. /*  The main code-generation routine.                   */
  1245. /*  f is the stream the code should be written to.      */
  1246. /*  p is a pointer to a doubly linked list of ICs       */
  1247. /*  containing the function body to generate code for.  */
  1248. /*  v is a pointer to the function.                     */
  1249. /*  offset is the size of the stackframe the function   */
  1250. /*  needs for local variables.                          */
  1251.  
  1252. void gen_code(FILE *f,struct IC *p,struct Var *v,zlong offset)
  1253. /*  The main code-generation.                                           */
  1254. {
  1255.   int c,t,i,addbuf,varargs=0,fixedgpr,fixedfpr,setcc,ccset;
  1256.   char *fpp;int fpf;struct IC *m;
  1257.   long of=(zl2l(offset)+3)/4*4,regbase,tmpoff;
  1258.   if(DEBUG&1) printf("gen_code()\n");
  1259.   for(c=1;c<=MAXR;c++) regs[c]=regsa[c];
  1260.   maxpushed=0;addbuf=0;
  1261.   for(m=p;m;m=m->next){
  1262.     c=m->code;t=m->typf&NU;
  1263.     if(c==ALLOCREG) {regs[m->q1.reg]=1;continue;}
  1264.     if(c==FREEREG) {regs[m->q1.reg]=0;continue;}
  1265.     if(c==COMPARE&&(m->q2.flags&KONST)){
  1266.       eval_const(&m->q2.val,t);
  1267.       if(zleqto(vlong,l2zl(0L))&&zdeqto(vdouble,d2zd(0.0))){
  1268.         m->q2.flags=0;m->code=c=TEST;
  1269.       }
  1270.     }
  1271.     if((t&NQ)<=LONG&&(m->q2.flags&KONST)&&(t&NQ)<=LONG&&(c==MULT||c==DIV||(c==MOD&&(t&UNSIGNED)))){
  1272.       eval_const(&m->q2.val,t);
  1273.       i=pof2(vlong);
  1274.       if(i){
  1275.         if(c==MOD){
  1276.           vlong=zlsub(vlong,l2zl(1L));
  1277.           m->code=AND;
  1278.         }else{
  1279.           vlong=l2zl(i-1);
  1280.           if(c==DIV) m->code=RSHIFT; else m->code=LSHIFT;
  1281.         }
  1282.         c=m->code;
  1283.         if((t&NU)==CHAR) m->q2.val.vchar=zl2zc(vlong);
  1284.         else if((t&NU)==SHORT) m->q2.val.vshort=zl2zs(vlong);
  1285.         else if((t&NU)==INT) m->q2.val.vint=zl2zi(vlong);
  1286.         else if((t&NU)==LONG) m->q2.val.vlong=vlong;
  1287.         vulong=zl2zul(vlong);
  1288.         if((t&NU)==(UNSIGNED|CHAR)) m->q2.val.vuchar=zul2zuc(vulong);
  1289.         else if((t&NU)==(UNSIGNED|SHORT)) m->q2.val.vushort=zul2zus(vulong);
  1290.         else if((t&NU)==(UNSIGNED|INT))  m->q2.val.vuint=zul2zui(vulong);
  1291.         else if((t&NU)==(UNSIGNED|LONG)) m->q2.val.vulong=vulong;
  1292.       }
  1293.     }
  1294.     if((c==CONVFLOAT||c==CONVDOUBLE)&&t!=FLOAT&&t!=DOUBLE&&addbuf<8) addbuf=8;
  1295.     if((t==FLOAT||t==DOUBLE)&&c>=CONVCHAR&&c<=CONVULONG&&addbuf<8) addbuf=8;
  1296.     if(c==CALL&&maxpushed<zl2l(m->q2.val.vlong)) maxpushed=zl2l(m->q2.val.vlong);
  1297.     if(c==CALL&&(m->q1.flags&VAR)&&!strcmp(m->q1.v->identifier,"__va_start")) varargs=1;
  1298.   }
  1299.   if(g_flags[9]&USEDFLAG) peephole(p);
  1300.   if(varargs){
  1301.     fixedgpr=fixedfpr=0;
  1302.     for(i=0;i<v->vtyp->exact->count;i++){
  1303.       c=(*v->vtyp->exact->sl)[i].styp->flags&NQ;
  1304.       if(c==POINTER||c<=LONG) fixedgpr++;
  1305.       if(c==FLOAT||c==DOUBLE) fixedfpr++;
  1306.     }
  1307.     regbase=of; /* merken */
  1308.     addbuf+=96;
  1309.   }
  1310.   of+=addbuf;tmpoff=minframe+maxpushed+of;
  1311.   function_top(f,v,of);
  1312.   if(varargs){
  1313.     regbase=frameoffset+regbase;
  1314.     fpp="";
  1315.     if(!(g_flags[8]&USEDFLAG)) fpp="r";
  1316.     for(i=fixedgpr;i<8;i++)
  1317.       fprintf(f,"\tstw\t%s%d,%ld(%s)\n",fpp,i+3,regbase+i*4,mregnames[sp]);
  1318.     if(!(g_flags[8]&USEDFLAG)) fpp="f";
  1319.     for(i=fixedfpr;i<8;i++)
  1320.       fprintf(f,"\tstfd\t%s%d,%ld(%s)\n",fpp,i+1,regbase+32+i*8,mregnames[sp]);
  1321.   }
  1322.   pushed=0;ccset=0;
  1323.   for(;p;pr(f,p),p=p->next){
  1324.     c=p->code;t=p->typf;
  1325.     if(c<0) {setcc=1;c=-c;} else setcc=0;
  1326.     if(c==NOP) {p->z.flags=0;continue;}
  1327.     if(c==ALLOCREG) {regs[p->q1.reg]=1;continue;}
  1328.     if(c==FREEREG) {regs[p->q1.reg]=0;continue;}
  1329.     if(c==LABEL) {ccset=0;fprintf(f,"%s%d:\n",labprefix,t);continue;}
  1330.     if(c==BRA) {ccset=0;fprintf(f,"\tb\t%s%d\n",labprefix,t);continue;}
  1331.     if(c>=BEQ&&c<BRA){
  1332.       ccset=0;
  1333.       if(!(p->q1.flags®)) p->q1.reg=cr0;
  1334.       if((g_flags[9]&USEDFLAG)&&!BTST(twice,p->typf-lastlabel)){
  1335.         struct IC *p2,*p3,*p4;int exit_label;
  1336.         p2=p->next;
  1337.         while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
  1338.         if(p2&&p2->code==SETRETURN&&p2->z.reg){p2->code=ASSIGN;p2->z.flags=REG;}
  1339.         if(p2&&p2->code==ASSIGN&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg<=32){
  1340.           p3=p2->next;
  1341.           while(p3&&(p3->code==FREEREG||p3->code==ALLOCREG)) p3=p3->next;
  1342.           if(p3&&p3->code==BRA){
  1343.             exit_label=p3->typf;
  1344.             p3=p3->next;
  1345.             while(p3&&(p3->code==FREEREG||p3->code==ALLOCREG)) p3=p3->next;
  1346.             if(p3&&p3->code==LABEL&&p3->typf==p->typf){
  1347.               p3=p3->next;
  1348.               while(p3&&(p3->code==FREEREG||p3->code==ALLOCREG)) p3=p3->next;
  1349.               if(p3&&p3->code==SETRETURN&&p3->z.reg){p3->code=ASSIGN;p3->z.flags=REG;}
  1350.               if(p3&&p3->code==ASSIGN&&(p3->z.flags&(REG|DREFOBJ))==REG&&p3->z.reg==p2->z.reg){
  1351.                 p4=p3->next;
  1352.                 while(p4&&(p4->code==FREEREG||p4->code==ALLOCREG)) p4=p4->next;
  1353.                 if(p4&&p4->code==LABEL&&p4->typf==exit_label){
  1354.                   int bit=(p->q1.reg-cr0)*4;
  1355.                   if((p2->q1.flags&KONST)&&(p3->q1.flags&KONST)){
  1356.                     eval_const(&p2->q1.val,p2->typf);
  1357.                     if(zleqto(vlong,l2zl(0L))){
  1358.                       eval_const(&p3->q1.val,p3->typf);
  1359.                       if(zleqto(vlong,l2zl(1L))||zleqto(vlong,l2zl(-1L))){
  1360.                         if(c==BLE){fprintf(f,"\tcror\t%d,%d,%d\n",bit,bit,bit+2);}
  1361.                         if(c==BGE){bit++;fprintf(f,"\tcror\t%d,%d,%d\n",bit,bit,bit+1);}
  1362.                         if(c==BNE){bit+=2;fprintf(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit);}
  1363.                         if(c==BGT) bit++;
  1364.                         if(c==BEQ) bit+=2;
  1365.                         fprintf(f,"\tmfcr\t%s\n",mregnames[t1]);
  1366.                         fprintf(f,"\trlwinm\t%s,%s,%d,%d,%d\n",mregnames[p2->z.reg],mregnames[t1],bit+1,31,31);
  1367.                         if(zleqto(vlong,l2zl(-1L))) fprintf(f,"\tneg\t%s,%s\n",mregnames[p2->z.reg],mregnames[p2->z.reg]);
  1368.                         if(BTST(twice,p4->typf-lastlabel)) fprintf(f,"%s%d:\n",labprefix,p4->typf);
  1369.                         p=p4;continue;
  1370.                       }
  1371.                     }else{
  1372.                       eval_const(&p3->q1.val,p3->typf);
  1373.                       if(zleqto(vlong,l2zl(0L))){
  1374.                         eval_const(&p2->q1.val,p2->typf);
  1375.                         if(zleqto(vlong,l2zl(1L))||zleqto(vlong,l2zl(-1L))){
  1376.                           if(c==BLE){fprintf(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit+2);}
  1377.                           if(c==BGE){bit++;fprintf(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit+1);}
  1378.                           if(c==BNE){bit+=2;}
  1379.                           if(c==BGT){bit++;fprintf(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit);}
  1380.                           if(c==BEQ){bit+=2;fprintf(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit);}
  1381.                           if(c==BLT){fprintf(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit);}
  1382.                           fprintf(f,"\tmfcr\t%s\n",mregnames[t1]);
  1383.                           fprintf(f,"\trlwinm\t%s,%s,%d,%d,%d\n",mregnames[p2->z.reg],mregnames[t1],bit+1,31,31);
  1384.                           if(zleqto(vlong,l2zl(-1L))) fprintf(f,"\tneg\t%s,%s\n",mregnames[p2->z.reg],mregnames[p2->z.reg]);
  1385.                           if(BTST(twice,p4->typf-lastlabel)) fprintf(f,"%s%d:\n",labprefix,p4->typf);
  1386.                           p=p4;continue;
  1387.                         }
  1388.                       }
  1389.                     }
  1390.                   }
  1391.                 }
  1392.               }
  1393.             }
  1394.           }
  1395.         }
  1396.       }
  1397.       fprintf(f,"\tb%s\t%s,%s%d\n",ccs[c-BEQ],mregnames[p->q1.reg],labprefix,t);
  1398.       continue;
  1399.     }
  1400.     if(c==MOVETOREG){
  1401.       if(p->z.reg<=32){
  1402.         load_reg(f,p->z.reg,&p->q1,INT,0);
  1403.       }else{
  1404.         if(p->z.reg>64) ierror(0);
  1405.         load_reg(f,p->z.reg,&p->q1,DOUBLE,0);
  1406.       }
  1407.       p->z.flags=0;
  1408.       continue;
  1409.     }
  1410.     if(c==MOVEFROMREG){
  1411.       if(p->q1.reg<=32){
  1412.         store_reg(f,p->q1.reg,&p->z,INT);
  1413.       }else{
  1414.         if(p->q1.reg>64) ierror(0);
  1415.         store_reg(f,p->q1.reg,&p->z,DOUBLE);
  1416.       }
  1417.       p->z.flags=0;
  1418.       continue;
  1419.     }
  1420.     if((c==ASSIGN||c==PUSH)&&((t&NQ)>POINTER||((t&NQ)==CHAR&&zl2l(p->q2.val.vlong)!=1))){
  1421.       unsigned long size,l;
  1422.       int a1,a2,b;char *ld,*st;
  1423.       size=zl2l(p->q2.val.vlong);
  1424.       a1=balign(&p->q1);
  1425.       if(c==ASSIGN) a2=balign(&p->z); else a2=0;
  1426.       b=1;ld=ldt[CHAR];st=sdt[CHAR];
  1427.       if(a1>=0&&a2>=0){
  1428.         if(a1==0&&a2==0){
  1429.           b=4;ld=ldt[INT];st=sdt[INT];
  1430.         }else if((a1&1)==0&&(a2&1)==0){
  1431.           b=2;ld=ldt[SHORT];st=sdt[SHORT];
  1432.         }
  1433.       }
  1434.       if(p->q1.flags&DREFOBJ){
  1435.         if(p->q1.am){
  1436.           if(p->q1.am->flags®_IND) fprintf(f,"\tadd\t%s,%s,%s\n",mregnames[t1],mregnames[p->q1.am->offset],mregnames[p->q1.am->base]);
  1437.           if(p->q1.am->flags&IMM_IND) fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[t1],mregnames[p->q1.am->base],p->q1.am->offset);
  1438.         }else{
  1439.           p->q1.flags&=~DREFOBJ;
  1440.           load_reg(f,t1,&p->q1,POINTER,t1);
  1441.           p->q1.flags|=DREFOBJ;
  1442.         }
  1443.       }else{
  1444.         load_address(f,t1,&p->q1,POINTER);
  1445.       }
  1446.       if(p->z.flags&DREFOBJ){
  1447.         if(p->z.am){
  1448.           if(p->z.am->flags®_IND) fprintf(f,"\tadd\t%s,%s,%s\n",mregnames[t2],mregnames[p->z.am->offset],mregnames[p->z.am->base]);
  1449.           if(p->z.am->flags&IMM_IND) fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[t2],mregnames[p->z.am->base],p->z.am->offset);
  1450.         }else{
  1451.           p->z.flags&=~DREFOBJ;
  1452.           load_reg(f,t2,&p->z,POINTER,t2);
  1453.           p->z.flags|=DREFOBJ;
  1454.         }
  1455.       }else{
  1456.         if(c==PUSH){
  1457.           pushed=(pushed+3)/4*4;
  1458.           fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[t2],mregnames[sp],pushed+minframe-b);
  1459.           pushed+=size;
  1460.         }else{
  1461.           load_address(f,t2,&p->z,POINTER);
  1462.         }
  1463.       }
  1464.       fprintf(f,"\taddi\t%s,%s,-%d\n",mregnames[t1],mregnames[t1],b);
  1465.       if(c==ASSIGN) fprintf(f,"\taddi\t%s,%s,-%d\n",mregnames[t2],mregnames[t2],b);
  1466.       l=size/(8*b);
  1467.       if(l>1){
  1468.         if(hi(l)) fprintf(f,"\tlis\t%s,%ld\n",mregnames[t3],hi(l));
  1469.         fprintf(f,"\tli\t%s,%ld\n",mregnames[t3],lo(l));
  1470.         fprintf(f,"\tmtctr\t%s\n",mregnames[t3]);
  1471.         fprintf(f,"%s%d:\n",labprefix,++label);
  1472.       }
  1473.       if(l>0){
  1474.         for(i=b;i<=7*b;i+=b){
  1475.           fprintf(f,"\tl%s\t%s,%d(%s)\n",ld,mregnames[t3],i,mregnames[t1]);
  1476.           fprintf(f,"\tst%s\t%s,%d(%s)\n",st,mregnames[t3],i,mregnames[t2]);
  1477.         }
  1478.         fprintf(f,"\tl%su\t%s,%d(%s)\n",ld,mregnames[t3],i,mregnames[t1]);
  1479.         fprintf(f,"\tst%su\t%s,%d(%s)\n",st,mregnames[t3],i,mregnames[t2]);
  1480.       }
  1481.       if(l>1){
  1482.         fprintf(f,"\tbdnz\t%s%d\n",labprefix,label);
  1483.       }
  1484.       size=size%(8*b);
  1485.       for(i=0;i<size/b;i++){
  1486.         fprintf(f,"\tl%su\t%s,%d(%s)\n",ld,mregnames[t3],b,mregnames[t1]);
  1487.         fprintf(f,"\tst%su\t%s,%d(%s)\n",st,mregnames[t3],b,mregnames[t2]);
  1488.       }
  1489.       size=size%b;i=b;
  1490.       if(size&2){
  1491.         fprintf(f,"\tl%su\t%s,%d(%s)\n",ldt[SHORT],mregnames[t3],b,mregnames[t1]);
  1492.         fprintf(f,"\tst%su\t%s,%d(%s)\n",sdt[SHORT],mregnames[t3],b,mregnames[t2]);
  1493.         i=2;
  1494.       }
  1495.       if(size&1){
  1496.         fprintf(f,"\tl%su\t%s,%d(%s)\n",ldt[CHAR],mregnames[t3],i,mregnames[t1]);
  1497.         fprintf(f,"\tst%su\t%s,%d(%s)\n",sdt[CHAR],mregnames[t3],i,mregnames[t2]);
  1498.       }
  1499.       p->z.flags=0;
  1500.       continue;
  1501.     }
  1502.     if(c==TEST&&((t&NQ)==FLOAT||(t&NQ)==DOUBLE)){
  1503.       p->code=c=COMPARE;
  1504.       p->q2.flags=KONST;
  1505.       p->q2.val.vdouble=d2zd(0.0);
  1506.       if((t&NQ)==FLOAT) p->q2.val.vfloat=zd2zf(p->q2.val.vdouble);
  1507.     }
  1508.     p=do_refs(f,p);
  1509.     c=p->code;
  1510.     if(c<0) {setcc=1;c=-c;} else setcc=0;
  1511.     if(c==SUBPFP) c=SUB;
  1512.     if(c==ADDI2P) c=ADD;
  1513.     if(c==SUBIFP) c=SUB;
  1514.     if(c>=CONVCHAR&&c<=CONVULONG){
  1515.       int to;
  1516.       static struct obj o;char *ip;
  1517.       long moff;int offreg;
  1518.       if(c==CONVCHAR) to=CHAR;
  1519.       if(c==CONVUCHAR) to=UNSIGNED|CHAR;
  1520.       if(c==CONVSHORT) to=SHORT;
  1521.       if(c==CONVUSHORT) to=UNSIGNED|SHORT;
  1522.       if(c==CONVINT) to=LONG;
  1523.       if(c==CONVUINT) to=UNSIGNED|LONG;
  1524.       if(c==CONVLONG) to=LONG;
  1525.       if(c==CONVULONG) to=UNSIGNED|LONG;
  1526.       if(c==CONVFLOAT) to=FLOAT;
  1527.       if(c==CONVDOUBLE) to=DOUBLE;
  1528.       if(c==CONVPOINTER) to=UNSIGNED|LONG;
  1529.       if(to==FLOAT||to==DOUBLE){
  1530.         if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  1531.           zreg=q1reg;
  1532.           continue;
  1533.         }
  1534.         if(tmpoff>32767){
  1535.           moff=0;offreg=t1;
  1536.           fprintf(f,"\taddis\t%s,%s,%ld\n",mregnames[offreg],mregnames[sp],hi(tmpoff));
  1537.           fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[offreg],mregnames[offreg],lo(tmpoff));
  1538.         }else{
  1539.           moff=tmpoff;
  1540.           offreg=sp;
  1541.         }
  1542.         if((t&NU)==(UNSIGNED|INT)||(t&NU)==(UNSIGNED|LONG)){
  1543.           o.flags=KONST;
  1544.           ip=(char *)&o.val.vdouble;
  1545.           ip[0]=0x41;
  1546.           ip[1]=0xe0;
  1547.           ip[2]=0x00;
  1548.           ip[3]=0x00;
  1549.           ip[4]=0x00;
  1550.           ip[5]=0x00;
  1551.           ip[6]=0x00;
  1552.           ip[7]=0x00;
  1553.           load_reg(f,f2,&o,DOUBLE,t2);
  1554.           fprintf(f,"\tfcmpu\t%s,%s,%s\n",mregnames[cr0],mregnames[q1reg],mregnames[f2]);
  1555.           fprintf(f,"\tcror\t3,2,1\n");
  1556.           fprintf(f,"\tbso\t%s,%s%d\n",mregnames[cr0],labprefix,++label);
  1557.           fprintf(f,"\tfctiwz\t%s,%s\n",mregnames[f2],mregnames[q1reg]);
  1558.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[DOUBLE],mregnames[f2],moff-8,mregnames[offreg]);
  1559.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[t&NQ],mregnames[zreg],moff-zl2l(sizetab[t&NQ]),mregnames[offreg]);
  1560.           fprintf(f,"\tb\t%s%d\n",labprefix,++label);
  1561.           fprintf(f,"%s%d:\n",labprefix,label-1);
  1562.           fprintf(f,"\tfsub\t%s,%s,%s\n",mregnames[f2],mregnames[q1reg],mregnames[f2]);
  1563.           fprintf(f,"\tfctiwz\t%s,%s\n",mregnames[f2],mregnames[f2]);
  1564.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[DOUBLE],mregnames[f2],moff-8,mregnames[offreg]);
  1565.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[INT],mregnames[zreg],moff-zl2l(sizetab[t&NQ]),mregnames[offreg]);
  1566.           fprintf(f,"\txoris\t%s,%s,32768\n",mregnames[zreg],mregnames[zreg]);
  1567.           fprintf(f,"%s%d:\n",labprefix,label);
  1568.         }else{
  1569.           fprintf(f,"\tfctiwz\t%s,%s\n",mregnames[f3],mregnames[q1reg]);
  1570.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[DOUBLE],mregnames[f3],moff-8,mregnames[offreg]);
  1571.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[t&NQ],mregnames[zreg],moff-zl2l(sizetab[t&NQ]),mregnames[offreg]);
  1572.         }
  1573.         if(t==CHAR) fprintf(f,"\textsb\t%s,%s\n",mregnames[zreg],mregnames[zreg]);
  1574.         continue;
  1575.       }
  1576.       if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  1577.         if(tmpoff>32767){
  1578.           moff=0;offreg=t1;
  1579.           fprintf(f,"\taddis\t%s,%s,%ld\n",mregnames[offreg],mregnames[sp],hi(tmpoff));
  1580.           fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[offreg],mregnames[offreg],lo(tmpoff));
  1581.         }else{
  1582.           moff=tmpoff;
  1583.           offreg=sp;
  1584.         }
  1585.         o.flags=KONST;
  1586.         ip=(char *)&o.val.vdouble;
  1587.         ip[0]=0x43;
  1588.         ip[1]=0x30;
  1589.         ip[2]=0x00;
  1590.         ip[3]=0x00;
  1591.         ip[4]=0x80;
  1592.         ip[5]=0x00;
  1593.         ip[6]=0x00;
  1594.         ip[7]=0x00;
  1595.         if((to&NU)==(UNSIGNED|INT)||(to&NU)==(UNSIGNED|LONG)){
  1596.           ip[4]=0x00;
  1597.           load_reg(f,f2,&o,DOUBLE,t2);
  1598.           fprintf(f,"\tlis\t%s,17200\n",mregnames[t2]);
  1599.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[INT],mregnames[q1reg],moff-4,mregnames[offreg]);
  1600.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[INT],mregnames[t2],moff-8,mregnames[offreg]);
  1601.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[DOUBLE],mregnames[zreg],moff-8,mregnames[offreg]);
  1602.           fprintf(f,"\tfsub\t%s,%s,%s\n",mregnames[zreg],mregnames[zreg],mregnames[f2]);
  1603.         }else{
  1604.           fprintf(f,"\tlis\t%s,17200\n",mregnames[t2]);
  1605.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[INT],mregnames[t2],moff-8,mregnames[offreg]);
  1606.           fprintf(f,"\txoris\t%s,%s,32768\n",mregnames[t2],mregnames[q1reg]);
  1607.           fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[INT],mregnames[t2],moff-4,mregnames[offreg]);
  1608.           fprintf(f,"\tl%s\t%s,%ld(%s)\n",ldt[DOUBLE],mregnames[zreg],moff-8,mregnames[offreg]);
  1609.           load_reg(f,f2,&o,DOUBLE,t2);
  1610.           fprintf(f,"\tfsub\t%s,%s,%s\n",mregnames[zreg],mregnames[zreg],mregnames[f2]);
  1611.         }
  1612.         continue;
  1613.       }
  1614.       if((t&NQ)>=(to&NQ)){
  1615.         if((t&UNSIGNED)==(to&UNSIGNED)){
  1616.           if(setcc){
  1617.             fprintf(f,"\tmr.\t%s,%s\n",mregnames[zreg],mregnames[q1reg]);
  1618.             ccset=1;
  1619.           }else{
  1620.             zreg=q1reg;
  1621.           }
  1622.           continue;
  1623.         }else{
  1624.           if((t&NU)==CHAR){
  1625.             fprintf(f,"\textsb%s\t%s,%s\n",record[setcc],mregnames[zreg],mregnames[q1reg]);
  1626.             ccset|=setcc;
  1627.           }else if((t&NU)==SHORT){
  1628.             fprintf(f,"\textsh%s\t%s,%s\n",record[setcc],mregnames[zreg],mregnames[q1reg]);
  1629.             ccset|=setcc;
  1630.           }else if((t&NU)==(UNSIGNED|CHAR)){
  1631.             fprintf(f,"\tandi.\t%s,%s,255\n",mregnames[zreg],mregnames[q1reg]);
  1632.             ccset=setcc;
  1633.           }else if((t&NU)==(UNSIGNED|SHORT)){
  1634.             fprintf(f,"\tandi.\t%s,%s,65535\n",mregnames[zreg],mregnames[q1reg]);
  1635.             ccset=setcc;
  1636.           }else{
  1637.             if(setcc){
  1638.               fprintf(f,"\tmr.\t%s,%s\n",mregnames[zreg],mregnames[q1reg]);
  1639.               ccset=1;
  1640.             }else{
  1641.               zreg=q1reg;
  1642.             }
  1643.           }
  1644.           continue;
  1645.         }
  1646.       }else{
  1647.         if((t&NU)==CHAR){
  1648.           fprintf(f,"\textsb%s\t%s,%s\n",record[setcc],mregnames[zreg],mregnames[q1reg]);
  1649.           ccset|=setcc;
  1650.         }else if((t&NU)==SHORT){
  1651.           fprintf(f,"\textsh%s\t%s,%s\n",record[setcc],mregnames[zreg],mregnames[q1reg]);
  1652.           ccset|=setcc;
  1653.         }else if((t&NU)==(UNSIGNED|CHAR)){
  1654.           fprintf(f,"\tandi.\t%s,%s,255\n",mregnames[zreg],mregnames[q1reg]);
  1655.           ccset=setcc;
  1656.         }else if((t&NU)==(UNSIGNED|SHORT)){
  1657.           fprintf(f,"\tandi.\t%s,%s,65535\n",mregnames[zreg],mregnames[q1reg]);
  1658.           ccset=setcc;
  1659.         }else{
  1660.           if(setcc){
  1661.             fprintf(f,"\tmr.\t%s,%s\n",mregnames[zreg],mregnames[q1reg]);
  1662.             ccset=1;
  1663.           }else{
  1664.             zreg=q1reg;
  1665.           }
  1666.         }
  1667.         continue;
  1668.       }
  1669.     }
  1670.     if(c==KOMPLEMENT){
  1671.       fprintf(f,"\tnor%s\t%s,%s,%s\n",record[setcc],mregnames[zreg],mregnames[q1reg],mregnames[q1reg]);
  1672.       ccset|=setcc;
  1673.       continue;
  1674.     }
  1675.     if(c==SETRETURN){
  1676.       if(p->z.reg){
  1677.         if(zreg==0) load_reg(f,p->z.reg,&p->q1,t,t3);
  1678.       }else
  1679.         ierror(0);
  1680.       continue;
  1681.     }
  1682.     if(c==GETRETURN){
  1683.       if(p->q1.reg)
  1684.         zreg=p->q1.reg;
  1685.       else
  1686.         p->z.flags=0;
  1687.       continue;
  1688.     }
  1689.     if(c==CALL){
  1690.       int reg;
  1691.       ccset=0;
  1692.       if((p->q1.flags&VAR)&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
  1693.         fprintf(f,"%s\n",p->q1.v->fi->inline_asm);
  1694.       }else{
  1695.         if(p->q1.flags&VAR){
  1696.           if(!strcmp("__va_start",p->q1.v->identifier)){
  1697.             fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[r3],mregnames[sp],framesize+minframe);
  1698.             continue;
  1699.           }
  1700.           if(!strcmp("__va_regbase",p->q1.v->identifier)){
  1701.             fprintf(f,"\taddi\t%s,%s,%ld\n",mregnames[r3],mregnames[sp],regbase);
  1702.             continue;
  1703.           }
  1704.           if(!strcmp("__va_fixedgpr",p->q1.v->identifier)){
  1705.             fprintf(f,"\tli\t%s,%d\n",mregnames[r3],fixedgpr);
  1706.             continue;
  1707.           }
  1708.           if(!strcmp("__va_fixedfpr",p->q1.v->identifier)){
  1709.             fprintf(f,"\tli\t%s,%d\n",mregnames[r3],fixedfpr);
  1710.             continue;
  1711.           }
  1712.         }
  1713.         if(g_flags[10]&USEDFLAG) fprintf(f,"\tcreqv\t6,6,6\n");
  1714.         if(q1reg){
  1715.           fprintf(f,"\tmtlr\t%s\n",mregnames[q1reg]);
  1716.           fprintf(f,"\tblrl\n");
  1717.         }else{
  1718.           fprintf(f,"\tbl\t");probj2(f,&p->q1,t);
  1719.           fprintf(f,"\n");
  1720.         }
  1721.       }
  1722.       pushed-=zl2l(p->q2.val.vlong);
  1723.       continue;
  1724.     }
  1725.     if((t&NQ)==FLOAT||(t&NQ)==DOUBLE) {fpp="f";fpf=1;} else {fpp="";fpf=0;}
  1726.     if(c==ASSIGN||c==PUSH){
  1727.       if(t==0) ierror(0);
  1728.       if(q1reg||c==PUSH){
  1729.         if(c==PUSH){
  1730.           if(zleqto(align[t&NQ],l2zl(8L))) pushed=(pushed+7)/8*8;
  1731.           if(q1reg)
  1732.             fprintf(f,"\tst%s\t%s,%ld(%s)\n",sdt[t&NQ],mregnames[q1reg],pushed+minframe,mregnames[sp]);
  1733.           pushed+=zl2l(p->q2.val.vlong);
  1734.           continue;
  1735.         }
  1736.         if(c==ASSIGN){
  1737.           if(setcc&&!fpf){
  1738.             fprintf(f,"\tmr.\t%s,%s\n",mregnames[zreg],mregnames[q1reg]);
  1739.             ccset=1;
  1740.           }else{
  1741.             zreg=q1reg;
  1742.           }
  1743.         }
  1744.         continue;
  1745.       }
  1746.     }
  1747.     if(c==ADDRESS){
  1748.       load_address(f,zreg,&p->q1,POINTER);
  1749.       continue;
  1750.     }
  1751.     if(c==MINUS){
  1752.       fprintf(f,"\t%sneg%s\t%s,%s\n",fpp,record[setcc&&!fpf],mregnames[zreg],mregnames[q1reg]);
  1753.       if(setcc&&!fpf) ccset=1;
  1754.       continue;
  1755.     }
  1756.     if(c==TEST){
  1757.       if(!(p->z.flags®))
  1758.         p->z.reg=cr0;
  1759.       if(!multiple_ccs&&(t&UNSIGNED)){
  1760.         struct IC *p2=p->next;
  1761.         while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
  1762.         if(!p2) ierror(0);
  1763.         if(p2->code==BGT) p2->code=BNE;
  1764.         else if(p2->code==BGE) p2->code=BRA;
  1765.         else if(p2->code==BLT) p2->code=NOP;
  1766.         else if(p2->code==BLE) p2->code=BEQ;
  1767.       }
  1768.       if(ccset&&p->z.reg==cr0) continue;
  1769.       if((t&NQ)==FLOAT||(t&NQ)==DOUBLE)
  1770.         ierror(0);
  1771.       else
  1772.         fprintf(f,"\tcmp%swi\t%s,%s,0\n",(t&UNSIGNED)?"l":"",mregnames[p->z.reg],mregnames[q1reg]);
  1773.       if(p->z.reg==cr0) ccset=0;
  1774.       continue;
  1775.     }
  1776.     if(c==COMPARE){
  1777.       if(!(p->z.flags®))
  1778.         p->z.reg=cr0;
  1779.       if((t&NQ)==FLOAT||(t&NQ)==DOUBLE)
  1780.         fprintf(f,"\tfcmpu\t%s,%s,",mregnames[p->z.reg],mregnames[q1reg]);
  1781.       else
  1782.         fprintf(f,"\tcmp%sw%s\t%s,%s,",(t&UNSIGNED)?"l":"",isimm[q2reg==0],mregnames[p->z.reg],mregnames[q1reg]);
  1783.       probj2(f,&p->q2,t);fprintf(f,"\n");
  1784.       if(p->z.reg==cr0) ccset=0;
  1785.       continue;
  1786.     }
  1787.     if(c==AND&&q2reg==0){
  1788.       ccset=setcc;
  1789.       fprintf(f,"\tandi.\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
  1790.       probj2(f,&p->q2,t|UNSIGNED);fprintf(f,"\n");
  1791.       continue;
  1792.     }
  1793.     if(c>=OR&&c<=AND){
  1794.       fprintf(f,"\t%s%s%s\t%s,%s,",logicals[c-OR],isimm[q2reg==0],record[setcc&&q2reg],mregnames[zreg],mregnames[q1reg]);
  1795.       probj2(f,&p->q2,t|UNSIGNED);fprintf(f,"\n");
  1796.       if(setcc&&q2reg) ccset=1;
  1797.       continue;
  1798.     }
  1799.     if(c==SUB&&(p->q1.flags&KONST)){
  1800.       fprintf(f,"\tsubfic\t%s,%s,",mregnames[zreg],mregnames[q2reg]);
  1801.       probj2(f,&p->q1,t&NQ);fprintf(f,"\n");
  1802.       continue;
  1803.     }
  1804.     if(c>=LSHIFT&&c<=MOD){
  1805.       if(c==RSHIFT&&!(t&UNSIGNED)){
  1806.         fprintf(f,"\tsraw%s%s\t%s,%s,",isimm[q2reg==0],record[setcc],mregnames[zreg],mregnames[q1reg]);
  1807.         probj2(f,&p->q2,t); fprintf(f,"\n");
  1808.         ccset|=setcc;
  1809.         continue;
  1810.       }
  1811.       if(c==MOD){
  1812.         i=0;
  1813.         if(zreg==q1reg||zreg==q2reg){
  1814.           if(t1!=q1reg&&t1!=q2reg) i=t1;
  1815.           if(t2!=q1reg&&t2!=q2reg) i=t2;
  1816.         }else i=zreg;
  1817.         if(i==0||i==q1reg||i==q2reg) ierror(0);
  1818.         fprintf(f,"\tdivw%s\t%s,%s,%s\n",(t&UNSIGNED)?"u":"",mregnames[i],mregnames[q1reg],mregnames[q2reg]);
  1819.         fprintf(f,"\tmullw\t%s,%s,%s\n",mregnames[i],mregnames[i],mregnames[q2reg]);
  1820.         fprintf(f,"\tsubf%s\t%s,%s,%s\n",record[setcc],mregnames[zreg],mregnames[i],mregnames[q1reg]);
  1821.         ccset|=setcc;
  1822.         continue;
  1823.       }
  1824.       if(c==DIV&&(t&UNSIGNED)){
  1825.         fprintf(f,"\tdivwu%s%s\t%s,%s,",isimm[q2reg==0],record[setcc&&q2reg],mregnames[zreg],mregnames[q1reg]);
  1826.         if(setcc&&q2reg) ccset=1;
  1827.       }else if(c==MULT&&((t&NQ)==FLOAT||(t&NQ)==DOUBLE)){
  1828.         fprintf(f,"\tfmul\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
  1829.       }else if(c==DIV&&((t&NQ)==FLOAT||(t&NQ)==DOUBLE)){
  1830.         fprintf(f,"\tfdiv\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
  1831.       }else if(c==MULT&&q2reg==0){
  1832.         fprintf(f,"\tmulli\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
  1833.       }else if(c==ADD&&setcc&&!q2reg){
  1834.         fprintf(f,"\taddic.\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
  1835.         ccset=1;
  1836.       }else{
  1837.         fprintf(f,"\t%s%s%s%s\t%s,%s,",fpp,arithmetics[c-LSHIFT],isimm[q2reg==0],record[setcc&&q2reg&&!fpf],mregnames[zreg],mregnames[q1reg]);
  1838.         if(setcc&&q2reg&&!fpf) ccset=1;
  1839.       }
  1840.       probj2(f,&p->q2,t&NQ);fprintf(f,"\n");
  1841.       continue;
  1842.     }
  1843.     ierror(0);
  1844.   }
  1845.   lastlabel=label;
  1846.   free(once);free(twice);
  1847.   function_bottom(f,v,of);
  1848. }
  1849.  
  1850. int shortcut(int code,int typ)
  1851. {
  1852.   return 0;
  1853. }
  1854.  
  1855. int reg_parm(struct reg_handle *m, struct Typ *t,int vararg)
  1856. {
  1857.   int f;
  1858.   if(!m) ierror(0);
  1859.   if(!t) ierror(0);
  1860.   if(vararg&&(g_flags[12]&USEDFLAG)) return 0;
  1861.   f=t->flags&NQ;
  1862.   if(f<=LONG||f==POINTER){
  1863.     if(m->gregs>=8) return 0;
  1864.     if(g_flags[12]&USEDFLAG){
  1865.       if(!(g_flags[13]&USEDFLAG)) m->fregs++;
  1866.       return -(r3-m->gregs++);
  1867.     }else{
  1868.       return r3-m->gregs++;
  1869.     }
  1870.   }
  1871.   if(f==FLOAT||f==DOUBLE){
  1872.     if(g_flags[12]&USEDFLAG){
  1873.       if(m->fregs>=13) return(0);
  1874.       if(!(g_flags[13]&USEDFLAG)){
  1875.         if(f==DOUBLE) m->gregs+=2; else m->gregs++;
  1876.       }
  1877.       return -(46-m->fregs++);
  1878.     }else{
  1879.       if(m->fregs>=8) return(0);
  1880.       return 46-m->fregs++;
  1881.     }
  1882.   }
  1883.   return 0;
  1884. }
  1885.  
  1886. void cleanup_cg(FILE *f)
  1887. {
  1888.   struct fpconstlist *p;
  1889.   unsigned char *ip;
  1890.   struct StatFPtrList *tfp,*fp=firstfptr;
  1891.  
  1892.   while(tfp=fp){
  1893.     fp=fp->next;
  1894.     free(tfp);
  1895.   }
  1896.   while(p=firstfpc){
  1897.     if(f){
  1898.       if((g_flags[12]&USEDFLAG)&&!use_sd(p->typ)){
  1899.         fprintf(f,"\t.tocd\n");
  1900.         fprintf(f,"%s%s%ld:\n",tocprefix,labprefix,zl2l(p->label));
  1901.         fprintf(f,"\t.long\t%s%ld\n",labprefix,zl2l(p->label));
  1902.         section=TOC;
  1903.       }
  1904.       if(use_sd(p->typ)){
  1905.         if(section!=TOC){fprintf(f,tocname);section=TOC;}
  1906.       }else{
  1907.         if(section!=RODATA){fprintf(f,rodataname);section=RODATA;}
  1908.       }
  1909.       if((p->typ&NQ)==DOUBLE)
  1910.         fprintf(f,"\t.align\t3\n");
  1911.       else
  1912.         fprintf(f,"\t.align\t2\n");
  1913.       fprintf(f,"%s%d:\n\t.long\t",labprefix,p->label);
  1914.       ip=(unsigned char *)&p->val.vdouble;
  1915.       fprintf(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
  1916.       if((p->typ&NQ)==DOUBLE){
  1917.         fprintf(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
  1918.       }
  1919.       fprintf(f,"\n");
  1920.     }
  1921.     firstfpc=p->next;
  1922.     free(p);
  1923.   }
  1924. }
  1925.  
  1926.  
  1927.